问题
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
device
field, which convert$$ROOT
object to array ink
andv
format using $objectToArray - $match you can match
device.v.number
to your number - $project to hide
device
field
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
$$ROOT
as$objectToArray
and insidein
checks condition if number is null using $ifNull then$add
number 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