In MongoDB i have documents with the following structure:
{
"_id": {
"$oid": "570794ee453b02a0001000001"
},
"fields_data": {
"572999c241f1590001000005": "Chicago",
"572999c241f1590001000007": "Male",
"572999c241f1590001000013": "Dr.",
"57299c0741f1590001000023": null,
"572999c241f1590001000017": "",
"589886d48570e90001000111": true,
"58762ac58570e9000100006a": true
}
}
fields_data object is very dynamic; the <field> of the object is not static.
Is it possible to search or filter only the values of the fields_data object?.
Something like:
$filter: {
input: "$fields_data",
as: "field",
cond: { $eq: [ "$$field.???", "Male" ] }
}
I'm using MongoDB 5.0.4 Community
EDIT/SOLUTION:
Thanks for the reply and help. The following worked for me.
<used within node>
[
{
'$project': {
'array': {
'$objectToArray': '$fields_data'
},
'doc': '$$ROOT'
}
}, {
'$match': {
'array.v': 'Male'
}
}, {
'$replaceRoot': {
'newRoot': '$doc'
}
}
]
CodePudding user response:
I think this is the answer you looking for basically you can use $where. I also agree with the comment that you might reconsider to have your fields_data be an array of objects with "name" and "value" fields so you can have straight normal queries.
CodePudding user response:
Query1
- filter the object and keep the field that is "Male"
- we cant construct paths dynamically, so the only way is to convert the object to array and filter.
objectToArrayto convert the embeded document to an array in the form
[{"k" : "key1", "v" : "value1"} ....]filterand keep only if"value"="Male"arrayToObjectto convert back to object like it was
*i think you should change your schema, fields are for the schema, not for saving data in general, if you do this queries become much more complicated and slower
aggregate(
[{"$set":
{"fields_data":
{"$filter":
{"input":{"$objectToArray":"$fields_data"},
"cond":{"$eq":["$$this.v", "Male"]}}}}},
{"$set":{"fields_data":{"$arrayToObject":["$fields_data"]}}}])
Query2
- filter the documents and keep those that have the "Male"
- works like the above but only to filter
aggregate(
[{"$match":
{"$expr":
{"$ne":
[{"$filter":
{"input":{"$objectToArray":"$fields_data"},
"cond":{"$eq":["$$this.v", "Male"]}}},
[]]}}}])
