Reputation: 16271
Assuming exists the following data for simplicity.
[
{
"special_colors": ["Blue", "Black", "Red"],
},
{
"special_colors": ["Blue", "Green", "Red"],
},
{
"special_colors": ["Black", "Blue", "Red"],
}
]
If I execute:
db.fighters.find({"special_colors.2": "Red"}, {"_id": 0}).pretty()
It works and returns all documents.
If I execute:
db.fighters.find({"special_colors.0": "Blue"}, {"_id": 0}).pretty()
It works and returns the first and second documents.
If I execute:
db.fighters.find({"special_colors.1" : "Blue"}, {"_id" : 0}).pretty()
It works and returns the third document.
To retrieve all the documents without matter in what position (index) is located either Blue or Black, I do the following and works fine:
db.fighters.find({"special_colors" : {$elemMatch: {$eq: "Blue"} } }, {"_id" : 0}).pretty()
Situation/Scenario
I want apply a OR, it to retrieve all the documents where special_colors
has either Blue
or Black
(without matter the position of index), I tried many variations such as:
db.fighters.find({"special_colors" : {$elemMatch: {$eq: "Blue", $eq: "Black"} } }, {"_id" : 0}).pretty()
when is executed returns some documents but only considered the second part (Black) and the first part (Blue) was totally ignored
With
db.fighters.find({"special_colors" : {$elemMatch: {$eq: ["Blue", "Black"]} } }, {"_id" : 0, }).pretty()
when is executed returns nothing
With
db.fighters.find({"special_colors" : {$elemMatch: {$or: ["Blue", "Black"] } } }, {"_id" : 0}).pretty()
when is executed arises the following error message: $or/$and/$nor entries need to be full objects
and with:
db.fighters.find({
"special_colors": {
$or: [{$elemMatch: {$eq: "Blue"}},
{$elemMatch: {$eq: "Black"}}
]
}
}, {"_id": 0}).pretty()
when is executed arises the following error message: unknown operator: $or
So what could be the correct syntax for OR
and AND
?
Therefore:
special_colors
has either Blue
or Black
(without matter the position of index)special_colors
has both Blue
and Black
(without matter the position of index)Upvotes: 1
Views: 107
Reputation: 36104
Retrieve all the documents where
special_colors
has eitherBlue
orBlack
(without matter the position of index)
$in
:
db.fighters.find({
special_colors: { $in: ["Blue", "Black"] }
},
{"_id" : 0}).pretty()
$or
: (equivelant to $in
)
$elemMatch
for array of stringdb.fighters.find({
$or: [
{ special_colors: "Blue" },
{ special_colors: "Black" }
]
},
{"_id" : 0}).pretty()
Retrieve all the documents where
special_colors
has bothBlue
andBlack
(without matter the position of index)
$all
:
$and
operation of the specified valuesdb.fighters.find({
special_colors: {
$all: ["Blue", "Black"]
}
},
{"_id" : 0}).pretty()
$and
: (equivelant to $all
)
db.fighters.find({
$and: [
{ special_colors: "Blue" },
{ special_colors: "Black" }
]
},
{"_id" : 0}).pretty()
Upvotes: 2
Reputation: 22276
While in theory you can use $elemMatch
for this it's more suited to be used for nested documents within the array. Because Mongo flattens all arrays for the purpose of queries you can just use $in for your "or" condition and $all for your "and" condition, like so:
db.collection.find({
special_colors: {
$in: [
"Blue",
"Black"
]
}
})
Will match any document that has blue or black.
And:
db.collection.find({
special_colors: {
$all: [
"Blue",
"Black"
]
}
})
Will match documents that have both colors in their array.
Upvotes: 1