I’m trying to make a $and
clause within a $match
clause. This $and
clause should have a full complete comparison against the string I’m providing. I’d like to make sure that the comparisong with attributes.value
should be exact the string I’m passing. With the following expression:
db.getCollection('cards').aggregate([{
"$match" : {
"$and" : [
{ "attributes.key" : "setCode", "attributes.value" : "qc" },
{ "attributes.key" : "code", "attributes.value" : "potions" }
]
}
}
As you can see, I get results that match with the code like potion
, potions
, cauldron potion
. I’m also getting results where other attributes with different keys, have the word potions
within.
Some sample data that is returned with the query above:
[
{
"_id": {"$oid": "66ab6eec2982eff57de4420f"},
"attributes": {
"name": "Gold Cauldron",
"code": "gold-cauldron",
"text": "To play this card, return 2 of your Potions Lessons from play to your hand.",
"illustrator": "Bob Petillo",
"orientation": "horizontal",
"set": "Quidditch Cup",
"setCode": "qc",
"type": "Item",
"typeCode": "item",
"rarity": "Foil Premium",
"rarityCode": "foil-premium",
"lessonType": "Potions",
"lessonTypeCode": "potions",
"lessonCost": "9",
"actionCost": "1",
"cardNumber": "7",
"providesLesson": "Potions",
"subType": ["Cauldron"]
},
"language": "en"
},
{
"_id": {"$oid": "66ab6eec2982eff57de44247"},
"attributes": {
"name": "Mopsus Potion",
"code": "mopsus-potion",
"text": "Do 3 damage to yout opponent or to a Creature of your choice.",
"illustrator": "Greg Hildebrandt",
"orientation": "vertical",
"set": "Quidditch Cup",
"setCode": "qc",
"type": "Spell",
"typeCode": "spell",
"rarity": "Common",
"rarityCode": "common",
"lessonType": "Potions",
"lessonTypeCode": "potions",
"lessonCost": "8",
"actionCost": "1",
"cardNumber": "63",
"subType": ""
},
"language": "en"
},
{
"_id": {"$oid": "66ab6eec2982eff57de44256"},
"attributes": {
"name": "Potions",
"code": "potions",
"text": "Provides 1 Potions lesson.",
"illustrator": "Shanth Enjeti, Melissa Ferreira",
"orientation": "horizontal",
"set": "Quidditch Cup",
"setCode": "qc",
"type": "Lesson",
"typeCode": "lesson",
"rarity": "Common",
"rarityCode": "common",
"lessonType": "Potions",
"lessonTypeCode": "potions",
"actionCost": "1",
"cardNumber": "78",
"providesLesson": "Potions",
"subType": ""
},
"language": "en"
}
]
So my $match
clause is not respecting the attributes.key
with values setCode
and code
, because it’s comparing with other attributes.
How can I make sure that the above $match
condition matches only the given keys and given values?
Thank you all!
2
Answers
It is possible to achieve the results I want by following @aneroid's suggestion with
$elemMatch
:If anyone knows a better way for achieving the same result with a simpler query, let me know!
Since
attributes
is an object and not an array of key-value fields, you don’t need to doattr.key
&attr.value
. (And you also wouldn’t need $elemMatch for your example data.)Use the keys & values directly in the match:
Mongo Playground
And unless you need an aggregation pipeline for some other steps, this can be used directly in a
find
query:Mongo Playground