MongoDB聚合查找和展开[重复]

Posted

技术标签:

【中文标题】MongoDB聚合查找和展开[重复]【英文标题】:MongoDB Aggregate Lookup and Unwind [duplicate] 【发布时间】:2019-03-04 20:26:19 【问题描述】:

我有这个问题:

我需要进行查询,获取外部数据(通过查找)、“多对多”和“一对多”。

我的数据看起来是这样的:

转让收藏:


  "_id": 1,
  "requests": [
    
       "service": 1,
       "foo": "foo1",
       "bar": "bar1"
    ,
    
       "service": 2,
       "foo": "foo2",
       "bar": "bar2"
    
  ]

所以,“service”字段,是另一个集合“services”的外部ID。

服务集合:

[ _id: 1, name: 'Service 1" ,  _id: 2, name: 'Service 2' ]

问题是:如何在 Transfer 集合中按服务名称进行过滤?我知道 mongoose 的填充,但这不允许通过外部数据进行过滤(另外,我的函数需要分页(我使用 mongoose-pagination 插件),因此,我在执行后丢弃过滤,因为这可以过滤少量数据宇宙)。

我相信最好的选择是使用聚合。 但是,如果我做这个......

db.transfers.aggregate([
   
    $lookup:  
      from: 'services', 
      localField: 'requests.service', 
      foreignField: '_id', 
      as: 'requests.service'
     
  
])

我知道了:


    "_id" : 1,
    "requests" : 
        "service" : [ 
            
                "_id" : 1,
                "name" : "Service 1"
            , 
            
                "_id" : 1,
                "name" : "Service 2"
            
        ]
    

如何在不改变查询的情况下将服务数据放入主体对象中?

显然,聚合函数在“请求”(很多)上添加了“展开”,而不是在“服务”(一个)上添加了“展开”

无论如何,我需要这个返回的数据:


    "_id" : 1,
    "requests": [
        
           "service": 
                "_id" : 1,
                "name" : "Service 1"
            ,
           "foo": "foo1",
           "bar": "bar1"
        ,
        
           "service": 
               "_id" : 2,
               "name" : "Service 2"
            ,
           "foo": "foo2",
           "bar": "bar2"
        
      ]

【问题讨论】:

所以您正试图让服务名称包含在每个 request 对象中? 【参考方案1】:

这是一种解决方案 - 现在不确定它是否是最漂亮的,但它确实可以完成工作:

db.transfers.aggregate([
    $lookup: 
        from: 'services',
        localField: 'requests.service',
        foreignField: '_id',
        as: 'requests2'
    
, 
    $project: 
        "requests": 
            $map: 
                "input": 
                    $zip: 
                        "inputs": [ "$requests", "$requests2" ]
                    
                ,
                "as": "this",
                "in": 
                    $mergeObjects: [
                         $arrayElemAt: [ "$$this", 0 ] ,
                         "service":  $arrayElemAt: [ "$$this", 1 ]  
                    ]
                
            
        
    
])

第二种选择是这样做:

db.transfers.aggregate([
    $lookup: 
        from: 'services',
        localField: 'requests.service',
        foreignField: '_id',
        as: 'requests2'
    
, 
    $project: 
        "requests": 
            $map: 
                "input": 
                    $range: [ 0,  $size: "$requests2"  ]
                ,
                "as": "index",
                "in": 
                    $mergeObjects: [
                         $arrayElemAt: [ "$requests", "$$index" ] ,
                         "service":  $arrayElemAt: [ "$requests2", "$$index" ]  
                    ]
                
            
        
    
])

我从未真正比较过这两个版本的性能,但我怀疑第二个版本要快一些。

【讨论】:

以上是关于MongoDB聚合查找和展开[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mongodb 聚合中展开嵌套对象数组?

MongoDB展开聚合查询给出意想不到的结果

MongoDB 查找和展开没有给出正确的结果

MongoDB,如何将查找和排序与聚合中的 $cond 结合起来?

MongoDB,如何将查找和排序与聚合中的 $cond 结合起来?

mongodb - 聚合因内存错误而失败