问题
I have next 3 documents in mongodb:
document 1:
{
"name": "device1",
"camera": {
"number": 3
}
}
document 2:
{
"name": "device2",
"camera": {
"number": 1
}
}
document 3:
{
"name": "device3",
"wifi": {
"number": 2
}
}
My aim is to find all devices which modules' number > 1, the module maybe camera, wifi or others.
I know I can use next to get the device:
> db.devices.find({"camera.number":{$gt:1}})
{ "_id" : ObjectId("5f436a3df716cb47d319245e"), "name" : "device1", "camera" : { "number" : 3 } }
> db.devices.find({"wifi.number":{$gt:1}})
{ "_id" : ObjectId("5f436a58f716cb47d3192460"), "name" : "device3", "wifi" : { "number" : 2 } }
But it looks I had to add something like "module.number" in query, you know maybe I have a lots of modules, then not so efficient to use camera.number, wifi.number & othermodule.number to find all matched devices. If possible I can have something magic to directly get the device which "has any module's number > 1", I mean no need to specify the parent field?
回答1:
I don't think it is possible with find() method but you can try aggregate() method,
- $addFields will add
devicefield, which convert$$ROOTobject to array inkandvformat using $objectToArray - $match you can match
device.v.numberto your number - $project to hide
devicefield
db.devices.aggregate([
{ $addFields: { device: { $objectToArray: "$$ROOT" } } },
{ $match: { "device.v.number": { $gt: 1 } } },
{ $project: { device: 0 } }
])
Playground
Another Possible Way with aggregate() method,
- match with $expr
- $reduce will input
$$ROOTas$objectToArrayand insideinchecks condition if number is null using $ifNull then$addnumber in initialValue otherwise add0.
db.collection.aggregate([
{
$match: {
$expr: {
$gt: [
{
$reduce: {
input: { $objectToArray: "$$ROOT" },
initialValue: 0,
in: { $add: ["$$value", { $ifNull: ["$$this.v.number", 0] }] }
}
},
1 // add your search number
]
}
}
}
])
Playground
回答2:
Simple, just change your schema.
https://mongoplayground.net/p/npSvVzbnsyk
{
"name": "device1",
"modules": [
{
"k": "camera",
"v": 3
}
]
},
{
"name": "device2",
"modules": [
{
"k": "wifi",
"v": 3
},
{
"k": "camera",
"v": 2
}
]
},
{
"name": "device3",
"modules": [
{
"k": "wifi",
"v": 2
}
]
}
db.collection.find({"modules.v": 3})
来源:https://stackoverflow.com/questions/63556589/how-to-directly-query-nested-field-without-specify-parent-field