【问题标题】:mongodb find documents where document has other than IDmongodb查找文档具有ID以外的文档
【发布时间】:2020-01-13 22:11:18
【问题描述】:

我的文档结构有点东西

{
   _id: name,
   dynamicDoc: {
     _id: id,
     fields....
   }
}

我想获取一个名称的所有动态文档,其中动态文档具有 _id 以外的字段。

{
  _id: "jack",
  order1:{
    _id: order897776,
    item names....
  },
  order2:{
    _id:order22789
  }
}

我想为杰克获取订单 1,因为订单没有订单。 order1 是一个动态字段。

【问题讨论】:

  • 举个例子来说明问题会很好
  • @chridam 请找一些虚拟的例子
  • 我觉得文档的建模应该不一样,比如有orders array,然后里面有像[{_id:"order897776", item_names:{name:item1}}, {_id:order22789}]这样的对象,它看起来像{_id:"jack", "orders:[{_id:"order897776", item_names:{name:item1}}, {_id:order22789}] }
  • 我也认为你不应该在已经有_id 的文档中使用_idinside 作为文档ID,而可以在子文档中使用id。在这种情况下,orders 的数组

标签: mongodb


【解决方案1】:

解决此问题的一种方法是运行一个聚合管道,以获取有关文档根级别的键的数据, 由系统变量$$ROOT 表示,遍历它们的值并确定它们是否具有多个键。

第一步,使用$addFields添加一个包含上述计算的额外字段并使用$objectToArray进行转换 [ { k: 'key name': v: 'value' }, ... ]数组的键/值对

db.collection.aggregate([
    { '$addFields': {
        'myKeys': { '$objectToArray': '$$ROOT' }
    } }
])

获得这个数组后,下一步将是迭代列表并将值字段转换为数组。 然后通过比较数组的大小来过滤值是必要的,如果它有多个元素,那就是你的人

db.collection.aggregate([
    { '$addFields': {
        'myKeys': { 
            '$map': {
                'input': { '$objectToArray': '$$ROOT' },
                'in': {
                    'k': '$$this.k',
                    'v': {
                        '$cond': [ // condition to convert the _id key value in ROOT to a single element array
                            { '$eq': ['$$this.k', '_id'] },
                            ['$$this.v'],
                            { '$objectToArray': '$$this.v' } // convert the rest of the keys at ROOT
                        ]
                    }
                }
            }
        }
    } }
])

过滤使用上一个管道的结果并检查数组大小:

db.collection.aggregate([
    { '$addFields': {
        'myKeys': { 
            '$map': {
                'input': { '$objectToArray': '$$ROOT' },
                'in': {
                    'k': '$$this.k',
                    'v': {
                        '$cond': [ // condition to convert the _id key value in ROOT to a single element array
                            { '$eq': ['$$this.k', '_id'] },
                            ['$$this.v'],
                            { '$objectToArray': '$$this.v' } // convert the rest of the keys at ROOT
                        ]
                    }
                }
            }
        }
    } },
    { '$addFields':{ 
        'myKeys': {
            '$filter': {
                'input': '$myKeys',
                'as': 'el',
                'cond': { 
                    '$gt': [{ '$size': '$$this.v'}, 1]
                }
            }
        }
    }}
])

这可以简化为单个管道,但会减少冗长:

db.collection.aggregate([
    { '$addFields':{ 
        'myKeys': {
            '$filter': {
                'input': { 
                    '$map': {
                        'input': { '$objectToArray': '$$ROOT' },
                        'in': {
                            'k': '$$this.k',
                            'v': {
                                '$cond': [
                                    { '$eq': ['$$this.k', '_id'] },
                                    ['$$this.v'],
                                    { '$objectToArray': '$$this.v' }
                                ]
                            }
                        }
                    }
                },
                'as': 'el',
                'cond': { 
                    '$gt': [{ '$size': '$$el.v'}, 1]
                }
            }
        }
    }}
])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多