Search for data in an array in a document in mongo - mongodb

I have a collection organization with field
users: [
{
"user_id":"1",
"role":"1"
},
{
"user_id":"2",
"role":"2"
}]
and another collection users with fields
{
{"user_id":1},
{"user_id":2},
{"user_id":3},
{"user_id":4}
}
I need to display all users with user id present in the users array in the organizations collection. What is the best way to implement this?

if you just want to display the user_id of the users in the organization you have to unwind users field and do the project on user_id field like below.
collection.aggregate([{"$unwind","$users"},{"$project":{"user_id":"$users.user_id"}}])

db.myDbCollection.find({}, {"user_id": 1});
can use this statement to find data from your collection.

Related

How can I query for a subdocument full of objects in Mongo?

So I have a document with an unknown number of objects in it, each with 2 properties. It's a collection of friend lists, and I'm trying to confirm if someone has a friend with a certain username before I allow a user to send a request. I'm keeping the list of friends in a subdocument, like this:
>>all the _id and other properties<<, "ownerFriends":[{"friendId":"an id goes here", "friendUsername": "username"}, {"friendId":"another id", "friendUsername":"username2"}]
I'm trying to do a query that will return username2 if given that as input, but I don't know how to do that with dot notation because I think you need to know the specific property to look for, and these are heterodox amounts of friend objects in the ownerFriends property.
If you want to select the ownerFriend object that has username as the friendUserName you can use the following selector (assuming your collection is called Friends):
Friends.find({
"ownerFriends.friendUsername": "username2"
}, {
fields: { "ownerFriends.$": 1}
});
You can find a detailed explanation of how to query an array of objects based on a property here:
http://www.curtismlarson.com/blog/2015/08/08/meteor-mongodb-array-property-selector/
In summary you have an object that contains keys, one of whose values is an array of objects. You can perform queries on the arrays using $elemMatch In your case:
MyCollection.find({ ownerFriends: { $elemMatch: { friendUsername: searchString }}});
Although I think you'll need to also query on the current user's _id. Not knowing the details of your collection, I can only speculate with:
MyCollection.find({ userId: Meteor.userId(), ownerFriends: { $elemMatch: { friendUsername: searchString }}});

Meteor: How do you populate a field from one collection into another collection with _id field?

In mongo I have a document that stores pending userId's in a collaborators object array and looks like this:
researchThread {
_id: 4374583575745756
pending: {
collaborators: [
{
userId: '13745845754745753'
},
{
userId: '23755845854745731'
},
{
userId: '33755845653741736'
}]
}
}
The userId is the _id field for the user from the users collection. Each user also has a name and an email field.
How can I populate the name and email fields from the user collection, into this document for each user in the researchThread.pending.collaborators object array? And also, will the populated data be reactive when used in the templates?
Loop through each collaborator, find the relevant user document by searching the users collection for the id, and update the researchThread document with that information.
The data will be reactive if the researchThread collection is a Meteor.Collection which you're drawing from in your templates.
However, why do you want to copy the user data? Why not just have Meteor query the users collection based on the researchThread userId when you need the data in the template?

Document References query example

If I choose to use Document References with a structure of Materialized Paths instead of the simple Embedded Documents how can I display the same results?
For example if I had Embedded docs I simply :
db.col.find({'user' : 'foo'})
and return:
{'user' : 'foo',
'posts' : [ {},
{},
{}
]
}
Which command should I use to display posts as an embedded array of that user? Or this can only happen client-side?
If it's document references,
users collection will contain:
{
_id : "foo",
// users details
}
and posts collection:
{
_id: "postid",
author: "foo"
// other fields
}
In this case,
1) First make query to get the user id from users collection.
2) Then send the user id to the posts collection to get all posts
var user = db.users.find({_id : "foo"});
// this is used to get user details or validate user and only after validation if you need to fetch the posts
var posts = db.posts.find({author: user._id });
As the documents are referenced, there will be a roundtrip to the server which is obvious.
I am not sure how you have used materialized path for this scenario, let me know the data structure of it and i would be able to mention the query based on that.

How to retrieve array of specific field of sub document- mongodb

This is my first mongodb project,I have this document structure in mongodb, I am trying to retrieve a particular user account (each user account has an array of contacts), from this user account, I will then obtain an array of the ID fields of the users contacts and then pass this array as a parameter to another query, I am doing this to avoid having to loop through the users contacts array in order to obtain the ID fields, here is the document structure, the query I tried is below it
{
name,
id,
contacts:[{
contactId, //I need an array of this field
dateAdded
},
contactId,
dateAdded
},
{}..]
}
//
var findByIdAll = function(accountId, callback) {
var self=this;
//Get the user account
Account.findOne({_id:accountId}, function(err,doc) {
/ After the user account has been obtained, the function below will
// use an array of the users contactsId's to fetch the contact's accounts
//please how do I obtain the array of contact Id's before reaching here
self.Account.find({_id:{$in:[/array of contact Ids]}},function(err,results){
callback(results);
});
});
};
EDIT
//I have now been able to obtain an array of contactID fields using the following query
var r=db.accounts.aggregate({$match:{email:'m#live.com'}},{$unwind:"$contacts"},
{$project:{_id:0,contacts:1}},{$group:{_id:'$_id',
list:{$push:'$contacts.accountId'}}});
The result I get from the query is
r
{
"result" : [
{
"_id" : null,
"list" : [
ObjectId("51c59a31c398c40c22000004"),
ObjectId("51c59a31c398c40c22000004")
]
}
],
"ok" : 1
}
A normal MongoDB query will always give you the entire document with the same structure.
If you want to get just part of the document or make a transformation to it you need to use the Aggregation Framework (is not as hard to understand as it looks, give it a try).
In your case you might have to use $unwind in contacts to explode the array, $match to get only the account you want, and $project to present the data as you want.

Modeling a user-to-item database in MongoDB

I've got two tables.
Movies, which lists all the movies in the database.
Users, which has the users.
Usually, I'd create a join table to connect a user to a movie (as in, the user likes a certain movie).
However, since you can't do that in MongoDB, what should I do? I want to be able to find all the movies a certain user likes, as well as all the users that like a certain movie, and movies that a given set of users like.
Embedded documents?
Thanks!
For a many-to-many relationship between movies and users like this, I'd probably have separate collections for each, but denormalise users who like a movie into the movies collection by embedding their _id and name fields into a likes array.
This way, you can retrieve the names of users who like a movie without having to make a separate lookup to the users collection, but still have extra user fields that won't be embedded inside movies.
The trade off is that you'd need to update both collections if a user changed their name, but I think that's a worthwhile cost.
db.movies
{
_id: <objectid>,
name:"Star Wars",
likes: [
{ userid: <user-objectid>, name: "John Smith" },
{ userid: <user-objectid>, name: "Alice Brown" }
]
}
db.users
{
_id: <objectid>,
name: "John Smith",
username: "jsmith",
passwordhash: "d131dd02c5e6eec4693d"
}
Movies a certain user likes
db.movies.find( { "likes.userid": <user-objectid> }, { "name": 1 } );
Users that like a certain movie
db.movies.find( { "_id": <movie-objectid> },
{ "likes.userid": 1, "likes.name": 1 } );
Movies that a given set of users like
db.movies.find( { "likes.userid":
{ $in: [ <user1-objectid>, <user2-objectid> ] } },
{ "name": 1 } );
You can do that in MongoDB, you just can't do the 'join' operation at the database level, you have to do it at the application level.
If you have millions of movies and millions of users you have to do it using a join collection because there is no way you can fit the number of likes for one movie or one user into either document.
Lookup the User and get their _id
Lookup the UserMovie documents with matching _id values
Lookup the Movies as necessary
The denormalization you might do here would be to store the Movie names in the UserMovie collection so you can display the movies a user likes without having to fetch each one from the Movie collection.
A possible optimization
One optimization you can try on this scheme is to create documents in the UserMovie collection which contain multiple relationships instead of using a single document for each relationship (like you would in SQL).
For example, if the most common access pattern is finding what movies a user likes, you could group them by user and put them in one or more documents indexed by that user id. Take a look at the StatementGroups in this blog post for a more complete explanation.