How to directly query nested field without specify parent field?

拥有回忆 提交于 2021-02-17 03:17:42

问题


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 in k and v 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 inside in checks condition if number is null using $ifNull then $add number in initialValue otherwise add 0.
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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!