I want to make an efficient query in MongoDb to find all users who have their userids listed in a usergroup. Ideally I want to make this as a single request to Mongodb. What I want corresponds to nested selects in SQL. I have tried this in the mongo shell:
db.user.save({_id:"u1", Name:"u1 name"});
db.user.save({_id:"u2", Name:"u1 name"});
db.user.save({_id:"u3", Name:"u3 name"});
db.usergroup.save({_id:"g1", Users: ["u2","u3"]});
Now here is the select I want to do, but without hardcoding the ["u2","u3"] array:
db.user.find({_id:{$in:["u2","u3"]}}).forEach(printjson);
This works fine and returns the user objects for u2 and u3.
Now the question is how to get the array of userids in the $in operator extracted with a query such that the entire query can be made with a single request.
A "nested query" like this does not work:
db.user.find({_id:{$in:db.usergroup.find({_id:"g1"},{_id:0,Users:1})}}).forEach(printjson);
Gives this error: Tue Mar 27 06:17:41 uncaught exception: error: { "$err" : "invalid query", "code" : 12580 } failed to load: mongoNestedSelect.js
1) is this possible in mongodb and how ?
2) how to do this with the official c# driver ?
MongoDB Nested Query Match on a Nested Field You can use the dot notation (“field. nestedField”) to specify query criteria for fields in embedded/nested documents. For queries that use dot notation, fields and nested fields must be enclosed in double-quotes.
Users can write SQL joins, then generate the equivalent mongo shell code, using the Query Code feature. They can then use this MongoDB “translation” to query any other appropriate MongoDB database, without additional support or libraries.
Or in other words, when a collection has a document, this document contains another document, another document contains another sub-document, and so on, then such types of documents are known as embedded/nested documents. In MongoDB, you can only nest document up to 100 levels.
The answer to such questions in MongoDB is often to denormalize your data. If you need just a list of the users in the group you could store the user Id and the user Name in the group document. In some ways you structure your database according to the result you want to see on screen rather than trying to put it in some normalized format.
Clearly that would only work if your user group list (with names) can fit in a single document, but your current approach has some limitations too concerning the maximum size of a group.
Another approach would be to store the groups that a user belongs to in an array on each 'User' document. Add an index on that array field and now you can find users by group. Given that a user is likely to belong to less groups than there are members in a group this may be the best approach here.
db.user.save({_id:"u1", name:"u1 name", groups:[{_id:"g1", name:"Group One"}, ...]});
Again you might store the group name with its _id so you can immediately display the list of groups a user belongs to with a single round trip. Of course, if you allow a group name to change you'll have to kick off a background task to go fix up all these copies of the name.
I would also use the built in MongoDB id generator rather than your own, it has many desirable properties.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With