使用对象数组查找 [英] Lookup with array of Objects

查看:55
本文介绍了使用对象数组查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图填充引用另一个集合的文档的两个对象数组.但是,结果中它总是显示为空数组,这让我感到惊讶.我在这里做错了什么?有没有更好的方法来填充" uploaded_files file_history ?

I am trying to populate two object arrays of my document which reference to another collection. However it always appears as an empty array in the results which surprises me. What am I doing wrong here? Is there a better way to 'populate' uploaded_files and file_history?

这是我的汇总声明:

    Project.aggregate(
        { $match: {"project_id": projectId}},
        { $addFields: {
            uploaded_files: {
                $filter: {
                    input: '$uploaded_files',
                    as: 'uploadedFile',
                    cond: {$eq: ['$$uploadedFile.upload_id', uploadId]}
                }
            },
            file_history: {
                $filter: {
                    input: '$file_history',
                    as: 'revision',
                    cond: {$eq: ['$$revision.upload_id', uploadId]}
                }
            },
        }},
        { $lookup: {
            from: 'users',
            localField: 'owner',
            foreignField: '_id',
            as: 'owner'
        }},
        { $lookup: {
            from: 'files',
            localField: 'uploaded_files.file',
            foreignField: '_id',
            as: 'test'
        }},
        { $lookup: {
            from: 'files',
            localField: 'file_history.file',
            foreignField: '_id',
            as: 'test2'
        }},
        { $unwind: '$owner' },
        { $limit: 1 }
    ).then(projects => {
        if (projects.length == 0)
            return res.status(404).send({ error: "Couldn't find a project with this id" })

        let project = projects[0]
})

我的文档如下:

{
    "_id" : ObjectId("5935a41f12f3fac949a5f925"),
    "project_id" : 13,
    "updated_at" : ISODate("2017-07-09T19:41:51.396Z"),
    "created_at" : ISODate("2017-06-05T18:34:07.150Z"),
    "owner" : ObjectId("591eea4439e1ce33b47e73c3"),
    "name" : "Demo project",
    "uploaded_files" : [ 
        {
            "display_name" : "001.jpg",
            "file" : ObjectId("596286ff7d3a594ed4797848"),
            "upload_id" : ObjectId("596286ff7d3a594ed4797849"),
            "created_at" : ISODate("2017-07-09T19:41:51.000Z")
        }
    ],
    "file_history" : [ 
        {
            "display_name" : "001.jpg",
            "file" : ObjectId("596286ff7d3a594ed4797848"),
            "upload_id" : ObjectId("596286ff7d3a594ed4797849"),
            "created_at" : ISODate("2017-07-09T19:41:51.000Z")
        }
    ]
}

推荐答案

您基本上需要

You basically need to $unwind the array first. MongoDB cannot yet work with the "inner" property of an object within an array as a source for $lookup.

为了提高效率,我们确实应该使用 $ concatArrays 首先加入"数组源,然后仅一个

Also for efficiency we really should use $concatArrays first to "join" the array source, and then only do one $lookup operation:

Project.aggregate([
  { "$match": { "project_id": projectId} },
  { "$project": {
    "project_id": 1,
    "updated_at": 1,
    "created_at": 1,
    "owner": 1,
    "name": 1,
    "combined": {
      "$concatArrays": [
        { "$map": {
          "input": {
            "$filter": {
              "input": "$uploaded_files",
              "as": "uf",
              "cond": { "$eq": ["$$uf.upload_id", uploadId ] }
            }
          },
          "as": "uf",
          "in": {
            "$arrayToObject": {
              "$concatArrays": [
                { "$objectToArray": "$$uf" },
                [{ "k": "type", "v": "uploaded_files" }]
              ]
            }
          }
        }},
        { "$map": {
          "input": {
            "$filter": {
              "input": "$file_history",
              "as": "fh",
              "cond": { "$eq": ["$$fh.upload_id", uploadId ] }
            }
          },
          "as": "fh",
          "in": {
            "$arrayToObject": {
              "$concatArrays": [
                { "$objectToArray": "$$fh" },
                [{ "k": "type", "v": "file_history" }]
              ]
            }
          }
        }}
      ]
    }
  }},
  { "$unwind": "$combined" },
  { "$lookup": {
    "from": "files",
    "localField": "combined.file",
    "foreignField": "_id",
    "as": "combined.file"
  }},
  { "$unwind": "$combined.file" },
  { "$lookup": {
    "from": "users",
    "localField": "owner",
    "foreignField": "_id",
    "as": "owner"
  }},
  { "$unwind": "$owner" },
  { "$group": {
    "_id": "$_id",
    "project_id": { "$first": "$project_id" },
    "updated_at": { "$first": "$updated_at" },
    "created_at": { "$first": "$created_at" },
    "owner": { "$first": "$owner" },
    "name": { "$first": "$name" },
    "combined": { "$push": "$combined" }
  }},
  { "$project": {
    "project_id": 1,
    "updated_at": 1,
    "created_at": 1,
    "owner": 1,
    "name": 1,
    "uploaded_files": {
      "$filter": {
        "input": "$combined",
        "as": "cf",
        "cond": { "$eq": [ "$$cf.type", "uploaded_files" ] }
      }    
    },
    "file_history": {
      "$filter": {
        "input": "$combined",
        "as": "cf",
        "cond": { "$eq": [ "$$cf.type", "file_history" ] }
      }    
    }
  }}
])

简而言之

  1. 将两个数组放在源上并标记它们,然后执行 $ lookup 以及合并后的详细信息和 $ unwind > 那个

    执行 $ lookup 以及其他 $ unwind 那个

    $ group 将文档与单个数组一起返回.

    $group the document back together with a single array.

    $ filter 通过标签名称"或类型"字段添加,以分隔"数组.

    $filter by the "tag names" or "type" field we added to "separate" the arrays.

    只需在每个数组上使用 $ unwind ,然后执行"join"并重新组合在一起,就可以遵循相同的过程.但是,实际上,除了首先简单地组合"之外,还需要更多的步骤.

    You can follow the same sort of process just be simply using $unwind on each array, then doing the "join" and grouping back together. But really that needs a lot more steps, than simply "combining" in the first place.

    还要注意,在服务器上进行处理时, $ lookup 后跟 $ unwind .有关详细信息,请参见聚合管道优化./p>

    Also note that $lookup followed by $unwind is actually treated as one pipeline stage when processed on the server. See Aggregation Pipeline Optimization for details

    这篇关于使用对象数组查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆