如何在 mongodb 中使用自动生成的 ID 查找数组元素

how to find array element using auto generated id in mongodb

目前,我正在为 MongoDB 文档系统的工作原理而苦恼。我想获取具有自动生成的 ID 的数组元素,但如何获取我不知道的特定数据。

我当前的架构是

const ItemPricesSchema = new mongoose.Schema({
    _id : {
        type: String
    },
    ItemsPrices: {
        type: [{
            barcode : {
                type: String
            },
            itemName : {
                type: String
            },
            price : {
                type: String
            }
        }]
    }
});

当前数据是这样存储的

{
    "_id": "sha@c.c",
    "ItemsPrices": [
        {
            "barcode": "345345",
            "itemName": "maggie",
            "price": "45",
            "_id": "620a971e11120abbde5f4c3a"
        },
        {
            "barcode": "356345",
            "itemName": "monster",
            "price": "70",
            "_id": "620a971e11120abbde5f4c3b"
        }
    ],
    "__v": 0
}

我想实现的是通过ids查找数组元素

如果我想要一个 ID 为“620a971e11120abbde5f4c3b”的特定数组元素,我应该怎么做?? 我试过 $unwind , $in, $match...

结果应该是这样的

{
    "_id": "sha@c.c",
    "ItemsPrices": [
        {
            "barcode": "356345",
            "itemName": "monster",
            "price": "70",
            "_id": "620a971e11120abbde5f4c3b"
        }
    ],
    "__v": 0
}

我试过的答案是这样的

router.get('/filter/:id', async (req, res) => {
    try {
        const item = await ItemPricesSchema.aggregate([
            {$project: {
                "ItemsPrices": {
                    $filter: {
                        input: "$ItemsPrices",
                        as: "item",
                        cond: {
                            $eq: [
                                "$$item._id",
                                "620a8dd1c88ae3eb88a8107a"
                               
                            ]
                        }

                    }
    
                }
    
            }
            }
        ])
        res.json(item);
        console.log(item);
        
    } catch (error) {
        res.status(500).json({message: error.message});
        
    }
})

和returns类似这样的东西(空数组)

[
  {
    "_id": "xvz@zyx.z",
    "ItemsPrices": []
  },
  {
    "_id": "zxc@xc.czx",
    "ItemsPrices: []
  },
  {
    "_id": "asd@asd.asd",
    "ItemsPrices": []
  },
  {
    "_id": "qwe@qwe.qwe",
    "ItemsPrices": []
  }
]

但如果我搜索价格 $$item.price


  cond: {
               $eq: [
                  "$$item.price",
                  "30"    
              ]
       }

它returns完美输出

[
  {
    "_id": "xvz@zyx.z",
    "ItemsPrices": []
  },
  {
    "_id": "zxc@xc.czx",
    "ItemsPrices: []
  },
  {
    "_id": "asd@asd.asd",
    "ItemsPrices": []
  },
  {
    "_id": "qwe@qwe.qwe",
    "ItemsPrices": [
        {
           "barcode":"234456345",
           "price":"30",
           "itemName":"monster",
           "_id":"620a8dd1c88ae3eb88a8107a"
        }
     ]
  }
]

您可以使用 $project 进行聚合并在数组部分应用 $filter。在猫鼬中,您可以或多或少类似的方式应用聚合查询 https://mongoosejs.com/docs/api/aggregate.html

db.collection.aggregate([
  {
    $project: {
      "ItemsPrices": {
        $filter: {
          input: "$ItemsPrices",
          as: "item",
          cond: {
            $eq: [
              "$$item._id",
              mongoose.Types.ObjectId("620a971e11120abbde5f4c3b")
            ]
          }
        }
      },
      "__v": 1  //when projecting 1 means in the final result this field appears
    }
  }
])

more examples

demo

选项 1:

在聚合查询中使用 $filter,如 cmgchess

所述

选项 2:

如果您只想要数组中的一个对象,您可以像这样使用 $elemMatch

db.collection.find({
  "ItemsPrices._id": "620a971e11120abbde5f4c3b"
},
{
  "ItemsPrices": {
    "$elemMatch": {
      "_id": "620a971e11120abbde5f4c3b"
    }
  }
})

示例here

但请注意,使用 $elemMatch 仅返回第一个元素。检查 this other example 其中有两个对象具有所需的 _id 但只有 returns 一个。

如前所述,如果你只有一个(或只存在一个),也许你可以使用 find$elemMatch 来避免整个数组的过滤器。但如果可以是多个值,则使用 $filter.