I have a collection with next data:
db.MyCollection.insert({
id: 1,
Location: [ 1, 1 ],
Properties: [ { Type: 1, Value: "a" }, { Type: 2, Value: "b" }, { Type: 3, Value: "c" } ]
});
db.MyCollection.insert({
id: 2,
Location: [ 1, 2 ],
Properties: [ { Type: 1, Value: "a" }, { Type: 2, Value: "a" }, { Type: 3, Value: "c" } ]
});
db.MyCollection.insert({
id: 3,
Location: [ 2, 1 ],
Properties: [ { Type: 1, Value: "a" }, { Type: 3, Value: "b" }, { Type: 3, Value: "a" } ]
});
db.MyCollection.insert({
id: 4,
Location: [ 2, 2 ],
Properties: [ { Type: 2, Value: "b" }, { Type: 2, Value: "a" }, { Type: 3, Value: "c" } ]
});
db.MyCollection.ensureIndex({ Location: "2d"});
db.MyCollection.ensureIndex({ "Properties.Type": 1, "Properties.Value": 1});
db.MyCollection.ensureIndex({ Location: "2d", "Properties.Type": 1, "Properties.Value": 1});
What I want is to find all items (using any of above indexes) that:
Here is my query (it doesn't work, but looks close to the right one):
db.MyCollection.find(
{
Location: { "$within": { "$center": [ [1, 1], 5 ] } },
Properties: {
$elemMatch: {
$and: [
{ Type: 1, Value: "a" },
{ Type: 2, Value: "b" }
]
}
}
})
Update:
The $all query works better as there is a problem with the $and one (see my comment in the JohnnyHK answer). Thanks for help.
In a case like this where you want the docs that include a specific set of array elements, you can use the $all
operator:
db.MyCollection.find(
{
Location: { "$within": { "$center": [ [1, 1], 5 ] } },
Properties: {
$all: [
{$elemMatch: { Type: 1, Value: "a" }},
{$elemMatch: { Type: 2, Value: "b" }}
]
}
})
To do it without the $all
operator you could use:
db.MyCollection.find(
{
Location: { "$within": { "$center": [ [1, 1], 5 ] } },
$and: [
{ Properties: {
$elemMatch: { Type: 1, Value: "a" }
}},
{ Properties: {
$elemMatch: { Type: 2, Value: "b" }
}}
]
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With