I have a MongoDB collection in the form of:
users: {
{
user_id: 1000,
activities: [
{id: 1, activity: 'swimming'},
{id: 2, activity: 'running'},
{id: 3, activity: 'biking'},...
]
},...
}
and I want to get the activity document that matches a specific ID. For example, if I query using {id: 1}
, I want an output of {id: 1, activity: 'swimming'}
. Currenlty, I’m trying to use findOne({activities: {$elemMatch: {id: 1}}})
, but it returns the entire user document (the user id, and all the activities).
The code I’m using is:
id = req.body.queryID;
db.collection('users').findOne({activities: {$elemMatch: {id}}})
.then((document) => {
console.log(document);
// more code after this
});
I’ve also tried to query using aggregate()
and findOne({}, {activities: {$elemMatch: {id}}})
, but I haven’t been able to figure it out.
I am on MongoDB version 4.4.8 according to db.version()
. Any help is appreciated!
3
Answers
You can use the
aggregate
method with theunwind
,match
andproject
pipelinesNOTE: This code is written using the mongo shell syntax.
The query does the following
unwind
pipeline which first pulls out all the items in the activities array.match
pipeline finds the array element that has the id we’re looking forproject
pipeline returns the output as desiredHope this helps
Please try as follow:
Your attempts look close, I think you just need to put them together.
findOne
takes two optional arguments, a query and a projection. The query tells MongoDB what document to look for and return. The projection document tells MongoDB what field(s) to include in the document returned by the query.What you have here:
Passes one argument, the query. It will look for a document where there is one element in the
activities
array with anid
equal to the value of the variableid
. You could also write this as:You’d also like to only return documents in the
activities
array with a matching ID. This is when you’d do something like your other attempt, where$elemMatch
is in the second argument, the projection:But because you passed an empty query, MongoDB will return any document, not necessarily one that contains an activity with a matching ID.
So if you pass both a query and the projection, I think you should get what you’re looking for. It might look like this:
This will include only the
_id
field and the matchingactivities
document if one exists. If you want to include other fields of the document, they need to be explicitly included. See this documentation about projection.