简体   繁体   English

MongoDB:连接多个数组

[英]MongoDB: Concatenate Multiple Arrays

I have 3 arrays of ObjectIds I want to concatenate into a single array, and then sort by creation date. 我有3个ObjectIds数组,我想连接成一个数组,然后按创建日期排序。 $setUnion does precisely what I want, but I'd like to try without using it. $ setUnion正是我想要的,但我想尝试不使用它。

Schema of object I want to sort: 我要排序的对象的模式:

var chirpSchema = new mongoose.Schema({
    interactions: { 
      _liked      : ["55035390d3e910505be02ce2"] // [{ type: $oid, ref: "interaction" }]
    , _shared     : ["507f191e810c19729de860ea", "507f191e810c19729de860ea"] //  [{ type: $oid, ref: "interaction" }]
    , _viewed     : ["507f1f77bcf86cd799439011"] //  [{ type: $oid, ref: "interaction" }]
  }
});

Desired result : Concatenate _liked, _shared, and _viewed into a single array, and then sort them by creation date using aggregate pipeline. 期望的结果 :将_liked,_shared和_viewed连接到一个数组中,然后使用aggregate管道按创建日期对它们进行排序。 See below 见下文

["507f1f77bcf86cd799439011", "507f191e810c19729de860ea", "507f191e810c19729de860ea", "55035390d3e910505be02ce2"]

I know I'm suppose to use $push , $each , $group , and $unwind in some combination or other, but I'm having trouble piecing together the documenation to make this happen. 我知道我想在某些组合或其他方面使用$push$each$group$unwind ,但是我很难拼凑文件来实现这一点。

Update: Query 更新:查询

model_user.aggregate([
      { $match    : { '_id' : { $in : following } } }
    , { $project  : { 'interactions' : 1 } }
    , { $project  : {
          "combined": { $setUnion : [ 
            "$interactions._liked"
          , "$interactions._shared"
          , "$interactions._viewed"
        ]}
      }}
])
.exec(function (err, data) {
  if (err) return next(err);
  next(data); // Combined is returning null
})

If all the Object _id values are "unique" then $setUnion is your best option. 如果所有Object _id值都是“唯一”,则$setUnion是您的最佳选择。 It is of course not "ordered" in any way as it works with a "set", and that does not guarantee order. 它当然不会以任何方式“排序”,因为它与“集合”一起使用,并且不保证顺序。 But you can always unwind and $sort. 但你总是可以放松和排序。

[
    { "$project": {
        "combined": { "$setUnion": [ 
            { "$ifNull": [ "$interactions._liked", [] ] },
            { "$ifNull": [ "$interactions._shared", [] ] },
            { "$ifNull", [ "$interactions._viewed", [] ] }
        ]}
    }},
    { "$unwind": "$combined" },
    { "$sort": { "combined": 1 } },
    { "$group": {
        "_id": "$_id",
        "combined": { "$push": "$combined" }
    }}
]

Of course again since this is a "set" of distinct values you can do the old way instead with $addToSet , after processing $unwind on each array: 当然,因为这是一个不同值的“集合”,所以在每个数组上处理$unwind之后,你可以用$addToSet来做旧方法:

[
    { "$unwind": "$interactions._liked" },
    { "$unwind": "$interactions._shared" },
    { "$unwind": "$interactions._viewed" },
    { "$project": {
        "interactions": 1,
        "type": { "$const": [ "liked", "shared", "viewed" ] }
    }}
    { "$unwind": "$type" },
    { "$group": {
        "_id": "$_id",
        "combined": {
            "$addToSet": {
                "$cond": [
                   { "$eq": [ "$type", "liked" ] },
                   "$interactions._liked",
                   { "$cond": [
                       { "$eq": [ "$type", "shared" ] },
                       "$interactions._shared",
                       "$interactions._viewed"
                   ]}
                ]
            }
        }
    }},
    { "$unwind": "$combined" },
    { "$sort": { "combined": 1 } },
    { "$group": {
        "_id": "$_id",
        "combined": { "$push": "$combined" }
    }}
]

But still the same thing applies to ordering. 但是同样的事情也适用于订购。

Future releases even have the ability to concatenate arrays without reducing to a "set": 未来版本甚至能够连接数组而不减少到“set”:

[
    { "$project": {
        "combined": { "$concatArrays": [ 
            "$interactions._liked",
            "$interactions._shared",
            "$interactions._viewed"
        ]}
    }},
    { "$unwind": "$combined" },
    { "$sort": { "combined": 1 } },
    { "$group": {
        "_id": "$_id",
        "combined": { "$push": "$combined" }
    }}
]

But still there is no way to re-order the results without procesing $unwind and $sort . 但是仍然没有办法在没有处理$unwind$sort情况下重新排序结果。

You might therefore consider that unless you need this grouped across multiple documents, that the basic "contenate and sort" operation is best handled in client code. 因此,您可能会认为,除非您需要将这些文档分组到多个文档中,否则基本的“contenate and sort”操作最好在客户端代码中处理。 MongoDB has no way to do this "in place" on the array at present, so per document in client code is your best bet. MongoDB目前无法在阵列上“就地”执行此操作,因此客户端代码中的每个文档都是您最好的选择。

But if you do need to do this grouping over multiple documents, then the sort of approaches as shown here are for you. 但是,如果您确实需要对多个文档进行分组,那么此处显示的方法就适合您。

Also note that "creation" here means creation of the ObjectId value itself and not other properties from your referenced objects. 另请注意,“创建”在这里意味着创建ObjectId值本身而不是引用对象的其他属性。 If you need those, then you perform a populate on the id values after the aggregation or query instead, and of course sort in client code. 如果您需要这些,那么您可以在聚合或查询之后对id值执行填充,当然也可以在客户端代码中进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM