Reputation: 335
I have no code to show as I do not know how to achieve what I want.
I have read that it is possible to return a sub document from a document, but I have not found out how to actually do this. A contrived example of a Users collection:
[
{
"_id":0,
"Name":"Person 1",
"Cupboard":[
{
"_id":0,
"Items":[
{
"_id":1,
"Name":"item 1"
},
{
"_id":2,
"Name":"item 2"
}
]
}
]
}
,
{
"_id":1,
"Name":"Person 2",
"Cupboard":[
{
"_id":0,
"Items":[
{
"_id":1,
"Name":"item 1"
},
{
"_id":2,
"Name":"item 2"
}
]
}
]
}
]
How do I ONLY return Items from a cupboard, assuming I know the cupboard's _id? I am using the C# driver, but even help doing it in the mongo shell would be useful.
Upvotes: 1
Views: 1948
Reputation: 14436
You could do something like
> db.users.find({"Cupboard._id": 0}, {"Cupboard.$" : 1}).pretty()
Which will return
{
"_id" : 0,
"Cupboard" : [
{
"_id" : 0,
"Items" : [
{
"_id" : 1,
"Name" : "item 1"
},
{
"_id" : 2,
"Name" : "item 2"
}
]
}
]
}
{
"_id" : 1,
"Cupboard" : [
{
"_id" : 0,
"Items" : [
{
"_id" : 1,
"Name" : "item 1"
},
{
"_id" : 2,
"Name" : "item 2"
}
]
}
]
}
>
However lets change our documents around so that we have the following, so that our users ahve multiple cupboards and some diffrent items in them too
> db.users.find().pretty()
{
"_id" : 0,
"Name" : "Person 1",
"Cupboard" : [
{
"_id" : 0,
"Items" : [
{
"_id" : 1,
"Name" : "item 1"
},
{
"_id" : 2,
"Name" : "item 2"
}
]
},
{
"_id" : 1,
"Items" : [
{
"_id" : 1,
"Name" : "item 1"
},
{
"_id" : 2,
"Name" : "item 2"
}
]
}
]
}
{
"_id" : 1,
"Name" : "Person 2",
"Cupboard" : [
{
"_id" : 0,
"Items" : [
{
"_id" : 1,
"Name" : "item 1"
},
{
"_id" : 2,
"Name" : "item 2"
}
]
},
{
"_id" : 2,
"Items" : [
{
"_id" : 21,
"Name" : "item 1"
},
{
"_id" : 22,
"Name" : "item 2"
}
]
}
]
}
We can now list all cupboards by user.
db.users.aggregate([
{$match: {"Cupboard._id": 0}},
{$project: {"Cupboard._id": 1}}
])
{ "_id" : 0, "Cupboard" : [ { "_id" : 0 }, { "_id" : 1 } ] }
{ "_id" : 1, "Cupboard" : [ { "_id" : 0 }, { "_id" : 2 } ] }
Upvotes: 1
Reputation: 6813
If you want to return many Items
you can use the aggregation framework's $unwind
to project the child items as the result of the query.
http://docs.mongodb.org/manual/reference/aggregation/unwind/
Then use $project
to return the results of the Items
Make sure you filter results early in the pipeline using $match
operator to make use of indexes.
You can create a pipeline as a BsonDocument. Here's an example:
var match = new BsonDocument
{
{
"$match",
new BsonDocument
{
{"Cupboard.Items._id", 123}
}
}
};
var match2 = new BsonDocument
{
/* other pipeline op */
};
var pipeline = new[] { match, match2 };
var result = coll.Aggregate(pipeline);
If however you want to return the User
documents (or part of) where a child Item
matches specific criteria you can simple use find.
db.Users.find({'Cupboard.Items._id':1234})
Hope that helps
Upvotes: 1
Reputation: 2606
All you need to do is project only the fields that you want. So on your dataset, return only items from cupboard will be:
db.collection.find({ ... }, { 'Cupboard.Items' : 1, _id : 0 })
Upvotes: 2