I struggle writing Mongo Queries. I can never understand why it doesn't return what I expect and yes I am reading the documentation but apparently to dumb to understand.
In Compass I write this query for a State collection with a document array of cities.
{"Cities.CityName":"Denver"}
This returns to me the State of Colorado document with ALL the cities in the document array. My sample below just shows one city document but they are all there.
{
"_id": {"$oid":"6146ada531696ee91a3f9fa4"},
"StateName": "Colorado",
"StateCode": "CO",
"Cities": [{
"_id": {"$oid":"6146ada531696ee91a3f5a50"},
"CityName": "Denver",
"Latitude": "39.55666000",
"Longitude": "-104.89609000"
}...]
}
OK so I'm thinking clearly we matched on the CityName now just project the _id of the City document.
{"Cities._id":1}
But this always returns to me the State document id NOT the matched City Document _id.
What am I doing wrong?
use case: The positional $ operator limits the contents of an <array>
to return the first element that matches the query condition on the array.
ex:
{ "Cities.$": 1 }
or {"Cities": { "$elemMatch": { "CityName": "Denver" } } }
result:
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}]
}
Note: You have to specify the required result fields in the projection!
find()
method:use case: Selects a subset of an array to return based on the specified condition. Returns an array with only those elements that match the condition. The returned elements are in the original order.
ex:
{
"Cities": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
}
}
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[{
"_id":{"$oid":"6146ada531696ee91a3f5a50"},
"CityName":"Denver",
"Latitude":"39.55666000",
"Longitude":"-104.89609000"
}...{}]
}
Note: You have to specify the required result fields in the projection!
$map
aggregation operator to select only _id
s from the Cities
array:use case: Applies an expression to each item in an array and returns an array with the applied results.
ex:
{
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
{
"_id":{"$oid":"6146ada531696ee91a3f9fa4"},
"Cities":[
{"$oid":"6146ada531696ee91a3f5a50"},
{"$oid":"6146ada531696ee91a3f5a51"},
....
]
}
Note: You have to specify the required result fields in the projection!
- ex:
$match
to check query condition$addFields
to add or format the existing properties$filter
and $map i have explained in 2) pointdb.collection.aggregate([
{ "$match": { "Cities.CityName": "Denver" } },
{
"$addFields": {
"Cities": {
"$map": {
"input": {
"$filter": {
"input": "$Cities",
"cond": { "$eq": ["$$this.CityName", "Denver"] }
}
},
"in": "$$this._id"
}
}
}
}
])
[
{
"Cities": [
ObjectId("6146ada531696ee91a3f5a50")
],
"StateCode": "CO",
"StateName": "Colorado",
"_id": ObjectId("6146ada531696ee91a3f9fa4")
}
]