如何在同一文档中加入数组? [英] How to Join Arrays in the Same Document?

查看:73
本文介绍了如何在同一文档中加入数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用两个数组的ID将数据合并到一个集合中.

I would like to combine the data in one collection using the IDs of the two arrays.

下面显示一个示例.

{
    "_id": ObjectId ("5976fd2eb0adec0a32fa9831"),
       "People": [
          {
            "_id": 1,      <--- ID
            "Name": "jane"
          },
          {
            "_id": 2,      <--- ID
            "Name": "Mark"
          }
       ],
       "Contents": [
          {
            "userID":  2,   <--- People ID
            "Text": "111"
          },
          {
            "userID":  1,   <--- People ID
            "Text": "Hi"
          }
       ]
}

我要制作以下文件.

{
    "_id": ObjectId ("5976fd2eb0adec0a32fa9831"),
    "People": [
       {
          "_id": 1,
          "Name" : "Jane"
       },
       {
          "_id": 2,
          "Name": "Mark"
       }
    ],
    "Contents": [
       {
          "userID": 2,
          "Name": "Mark",    <-- Adding
          "Text": "111",

      },
       {
          "userID": 1,
          "Name": "Jane",    <-- Adding
          "Text": "Hi",

      }
    ]
}

我尝试了诸如.aggregate()$lookup$unwind之类的各种操作,但无法获得结果.

I have tried various things like $lookup or $unwind of .aggregate() but I cannot get the result.

推荐答案

您要 $indexOfArray 理想情况:

You want $map and $indexOfArray ideally:

db.collection.aggregate([
  { "$addFields": {
    "Contents": {
      "$map": {
        "input": "$Contents",
        "as": "c",
        "in": {
          "userID": "$$c.userID",
          "Name": {
            "$arrayElemAt": [
              "$People.Name",
              { "$indexOfArray": [ "$People._id", "$$c.userID" ] }
            ]
          },
          "Text": "$$c.Text"
        }
      }
    }
  }}
])

基本上,这是通过 表示 .

Which basically grabs the value from the other array via $arrayElemAt for the matching "index" returned by $indexOfArray.

如果您的MongoDB需要回退没有该运算符的版本,则可以使用 $filter 代替:

If your MongoDB needs to fall back a version without that operator, then you could use $filter instead:

db.collection.aggregate([
  { "$addFields": {
    "Contents": {
      "$map": {
        "input": "$Contents",
        "as": "c",
        "in": {
          "userID": "$$c.userID",
          "Name": {
            "$arrayElemAt": [
              { "$map": {
                "input": { 
                  "$filter": {
                    "input": "$People",
                    "as": "p",
                    "cond": { "$eq": [ "$$p._id", "$$c.userID" ] }
                  }
                },
                "as": "p",
                "in": "$$p.Name"
              }},
              0
            ]
          },
          "Text": "$$c.Text"
        }
      }
    }
  }}
])

基本上,您在其中 $filter 结果比较其他数组,并只需使用0索引返回 first 匹配元素/aggregation/arrayElemAt/"rel =" nofollow noreferrer> $arrayElemAt .

Where basically you $filter the results down of the other array in comparison and simply return the first matching element by the 0 index with $arrayElemAt.

无论哪种情况,都不需要使用

In either case, there is no need to "self-join" using $lookup, and that's just really unnecessary overhead best avoided.

从问题文档中,您将获得以下信息:

From the document in the question you get the following:

/* 1 */
{
    "_id" : ObjectId("5976fd2eb0adec0a32fa9831"),
    "People" : [ 
        {
            "_id" : 1.0,
            "Name" : "jane"
        }, 
        {
            "_id" : 2.0,
            "Name" : "Mark"
        }
    ],
    "Contents" : [ 
        {
            "userID" : 2.0,
            "Name" : "Mark",
            "Text" : "111"
        }, 
        {
            "userID" : 1.0,
            "Name" : "jane",
            "Text" : "Hi"
        }
    ]
}


尽管如此,一般来讲,根本没有任何聚合运算符的原因,因为通常最好将这种运算留给游标进行后处理.实际上,由于实际上是在向文档添加"数据以返回,所以最好在通过网络发送文档之后进行修改.


Generally speaking though, there is no such reason for any aggregation operators at all, as this sort of operation is generally best left to post-processing in the cursor. In fact since you are actually "adding" data to the document to return, it's better to do modification after the document is sent over the network.

作为上述的常见用法,如外壳程序的JavaScript所示:

As a common idiom of the above shown as JavaScript for the shell:

db.collection.find().map( d => 
  Object.assign(
    d,
    {
      "Contents": d.Contents.map( c => 
        Object.assign(c, 
          { "Name": d.People.map(p => p.Name)[d.People.map(p => p._id).indexOf(c.userID)] }
        )
      )
    }
  )
)

产生完全相同的结果,并且通常在眼睛上更易于阅读和解释

Produces the exact same result, and is generally a bit easier on the eyes to read and interpret

这篇关于如何在同一文档中加入数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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