I have an array of ids like so:
[5, 7, 9, 4, 18]
I have a collection with documents that are inserted with the following format:
db.collection('groups').insert(
[
{
members: [
{member: 5, hasSeen: false, requiresAction: true},
{member: 7, hasSeen: true, requiresAction: true},
{member: 4, hasSeen: false, requiresAction: false}
]
},
{
members: [
{member: 5, hasSeen: false, requiresAction: true},
{member: 4, hasSeen: false, requiresAction: false},
{member: 7, hasSeen: true, requiresAction: true},
{member: 9, hasSeen: false, requiresAction: false},
{member: 18, hasSeen: false, requiresAction: false}
]
},
{
members: [
{member: 7, hasSeen: true, requiresAction: true},
{member: 9, hasSeen: false, requiresAction: false},
{member: 4, hasSeen: false, requiresAction: false},
{member: 18, hasSeen: false, requiresAction: false},
{member: 1, hasSeen: false, requiresAction: false},
{member: 5, hasSeen: false, requiresAction: true}
]
}
]
);
I would like to find all documents in the collection "groups" that contain only the "member" ids in the above array, and order shouldn't matter. For example, if the search was conducted with the above array, only the second inserted document would be returned from above.
You'll need to employ the use of MongoDB's aggregation pipeline to find the required document(s).
The steps to be employed in the aggregation are listed below:
Denormalize each of the documents by deconstructing the members
array.
This can be achieved by using the $unwind aggregation operator:
Deconstructs an array field from the input documents to output a document for each element. Each output document is the input document with the value of the array field replaced by the element.
The $unwind
operator will split each document into several, each new document containing a members
field that has a single member object:
{_id: 'first_id', members: {member: 4, hasSeen: false}} {_id: 'first_id', members: {member: 5, hasSeen: fasee}}
To use the $unwind
operator, we'd simply add this to the aggregation pipeline:
{$unwind: "$members"}
Group the documents by their _id
fields, adding the member ids to an array
This can be achieved by using the $group aggregation operator:
Groups documents by some specified expression and outputs to the next stage a document for each distinct grouping. The output documents contain an _id field which contains the distinct group by key. The output documents can also contain computed fields that hold the values of some accumulator expression grouped by the $group's _id field.
The $group
operator would allow us to group the denormalized documents by their ids while accumulating the member ids so we'll obtain documents of this form:
{_id: 'first_id', member_ids: [5, 7, 4] }
The expression required to group the documents and accumulate the ids is:
{$group: { _id: "$_id", member_ids: { $push: "$members.member" } }}
Filter the resulting documents according to the defined criteria
This can be achieved by using the $match aggregation operator:
Filters the documents to pass only the documents that match the specified condition(s) to the next pipeline stage.
To obtain documents whose member_ids
attribute matches the criteria, the expression is:
{$match: {'member_ids': { $all: [5, 7, 9, 4, 18] } } }
The final aggregation query would be:
db.collection('groups').aggregate(
[
{$unwind: "$members"},
{$group: {
_id: "$_id",
member_ids: { $push: "$members.member" }
}},
{$match: {'member_ids': { $all: [5, 7, 9, 4, 18] } } }
]
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.