【问题标题】:Filter MongoDB query to find documents only if a field in a list of objects is not empty仅当对象列表中的字段不为空时过滤 MongoDB 查询以查找文档
【发布时间】:2020-03-13 23:13:30
【问题描述】:

我有一个 MongoDB 文档结构,如下所示:

结构

{
    "stores": [
        {
            "items": [
                {
                    "feedback": [],
                    "item_category": "101",
                    "item_id": "10"
                },
                {
                    "feedback": [],
                    "item_category": "101",
                    "item_id": "11"
                }
            ]
        },
        {
            "items": [
                {
                    "feedback": [],
                    "item_category": "101",
                    "item_id": "10"
                },
                {
                    "feedback": ["A feedback"],
                    "item_category": "101",
                    "item_id": "11"
                },
                {
                    "feedback": [],
                    "item_category": "101",
                    "item_id": "12"
                },
                {
                    "feedback": [],
                    "item_category": "102",
                    "item_id": "13"
                },
                {
                    "feedback": [],
                    "item_category": "102",
                    "item_id": "14"
                }
            ],
            "store_id": 500
        }
    ]
}

这是集合中的单个文档。删除某些字段以生成数据的最小表示。

我想要的是仅当 items 数组中的 feedback 字段不为空时才获取项目。预期结果是:

预期结果

{
    "stores": [
        {
            "items": [
                {
                    "feedback": ["A feedback"],
                    "item_category": "101",
                    "item_id": "11"
                }
            ],
            "store_id": 500
        }
    ]
}

这是我根据this 中的示例尝试的方法,我认为情况几乎相同,但它不起作用。我的查询有什么问题,链接中的 zipcode search 示例中的情况是否相同?它返回第一个 JSON 代码中的所有内容,结构

我尝试了什么

query = {
    'date': {'$gte': since, '$lte': until},
    'stores.items': {"$elemMatch": {"feedback": {"$ne": []}}}
}

谢谢。

【问题讨论】:

  • 你在 stores 数组的第一个对象中也有 store_id 吗?请提及您的 mongoDB 版本..
  • 它是否有效或仍有问题?
  • 我试过了,但实际上还是有问题。我会通知你更多。感谢您的回答。

标签: python mongodb pymongo


【解决方案1】:

请试试这个:

db.yourCollectionName.aggregate([
{ $match: { 'date': { '$gte': since, '$lte': until }, 'stores.items': { "$elemMatch": { "feedback": { "$ne": [] } } } } },
{ $unwind: '$stores' },
{ $match: { 'stores.items': { "$elemMatch": { "feedback": { "$ne": [] } } } } },
{ $unwind: '$stores.items' },
{ $match: { 'stores.items.feedback': { "$ne": [] } } },
{ $group: { _id: { _id: '$_id', store_id: '$stores.store_id' }, items: { $push: '$stores.items' } } },
{ $project: { _id: '$_id._id', store_id: '$_id.store_id', items: 1 } },
{ $group: { _id: '$_id', stores: { $push: '$$ROOT' } } },
{ $project: { 'stores._id': 0 } }
])

我们已经完成了所有这些阶段,因为您需要对数组进行操作,此查询是假设您正在处理大量数据而编写的,因为您正在过滤日期以防万一您的文档大小在第一个$match 之后要少得多,那么您可以避免关注位于两个$unwind 之间的$match 阶段。

参考:

$match, $unwind, $project, $group

【讨论】:

    【解决方案2】:

    此聚合查询获得所需的结果(使用提供的示例文档并从 mongo shell 运行):

    db.stores.aggregate( [
      { $unwind: "$stores" },
      { $unwind: "$stores.items" },
      { $addFields: { feedbackExists: { $gt: [ { $size: "$stores.items.feedback" }, 0 ] } } },
      { $match: { feedbackExists: true } },
      { $project: { _id: 0, feedbackExists: 0 } }
    ] )
    

    【讨论】:

      猜你喜欢
      • 2019-07-11
      • 1970-01-01
      • 2018-08-08
      • 2022-01-09
      • 2012-01-23
      • 2019-07-11
      • 1970-01-01
      • 1970-01-01
      • 2015-05-18
      相关资源
      最近更新 更多