Reputation: 858
I have a families
collection. The documents in it have a users
array. Given this family document:
{
"id" : "1",
"users" : [
{
"id" : "2",
"identities" : [
{
"type" : "email",
"email" : "foo"
},
{
"type" : "email",
"email" : "bar"
}
]
},
{
"id" : "3",
"identities" : [
{
"type" : "email",
"email" : "baz"
},
{
"type" : "email",
"email" : "qux"
}
]
}
]
}
I want to project the type
field of the identities
array elements, but only from the specific user I am querying. The positional operator gets the right user:
db.families.findOne(
{ 'users.id': '2' },
{ 'users.$': 1 }
)
And I can specify the field I'm interested in with:
db.families.findOne(
{ 'users.id': '2' },
{ 'users.identities.type': 1 }
)
But when combining both, only the positional operator is respected:
db.families.findOne(
{ 'users.id': '2' },
{ 'users.$': 1, 'users.identities.type': 1 }
)
(That returns user with id 2, but returns the identities array elements with all fields). Thought about trying this:
db.families.findOne(
{ 'users.id': '2' },
{ 'users.$.identities.type': 1 }
)
But it's no good since per the docs:
MongoDB ignores the part of the path that follows the $
Is there a way to do it?
Upvotes: 1
Views: 1096
Reputation: 10697
This will project only the type & users.id for the selected users.id:
db.families.findOne({"users.id":"2"},{"users":{id:1,"identities.type.$":1}})
{
"_id" : ObjectId("601f1974cf95940e8e0c814e"),
"users" : [
{
"id" : "2",
"identities" : [
{
"type" : "email"
},
{
"type" : "email"
}
]
}
]
}
( Tested in mongod 4.4.3 ) Can be re-written also like this ( also 4.4.3 ):
db.families.findOne({"users.id":"2"},{"users":{id:1,"identities":{"type.$":1}}})
Same result in mongod 4.2.12 can be achieved with following aggregation:
db.families.aggregate([
{$project:{users:{$filter:{input:"$users",as:"us",cond:{$eq:["$$us.id","2"]}}}}} ,
{$project:{"users.identities.type":1 , "users.id":1 }}
])
aggregation explained:
Upvotes: 1
Reputation: 1680
You only have to use the $ operator to project an field.
Query:
db.collection.find({
"users.id": "2"
},
{
"users.identities.type.$": 1
});
Result:
[
{
"_id": "1",
"users": [
{
"identities": [
{
"type": "email"
},
{
"type": "email"
}
]
}
]
}
]
Upvotes: 0