【问题标题】:MongoDB: Concatenate Multiple ArraysMongoDB:连接多个数组
【发布时间】:2015-12-27 16:57:09
【问题描述】:

我有 3 个 ObjectIds 数组我想连接成一个数组,然后按创建日期排序。 $setUnion 正是我想要的,但我想尝试不使用它。

我要排序的对象的架构:

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" }]
  }
});

所需结果:将 _liked、_shared 和 _viewed 连接到一个数组中,然后使用 aggregate 管道按创建日期对它们进行排序。见下文

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

我知道我应该以某种组合方式使用$push$each$group$unwind,但我无法将文档拼凑起来以实现这一目标。

更新:查询

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
})

【问题讨论】:

  • Whist “连接”数组是可能的,“按日期排序” 是不可能的。您似乎在另一个集合中的引用数据中引用诸如“日期”之类的信息。 MongoDB 不以任何方式执行连接,并且 mongoose populate 也不是连接,也不能在聚合管道的中间执行。也就是说,ObjectId 值包含一个日期组件,因此如果足够的话,它们至少会按照创建顺序进行排序。
  • @BlakesSeven,对不起,我没有更具体。我需要按创建顺序排序。您能否展示连接是如何完成的,或者指出我的资源?

标签: node.js mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

如果所有对象_id 的值都是“唯一的”,那么$setUnion 是您的最佳选择。它当然不是以任何方式“有序”的,因为它与“集合”一起使用,这并不能保证有序。但你总是可以放松和 $sort。

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

当然,因为这是一组不同值的“集合”,您可以在每个数组上处理 $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" }
    }}
]

但同样的事情也适用于订购。

未来的版本甚至可以连接数组而不减少为“集合”:

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

但如果不处理 $unwind$sort,仍然无法重新排序结果。

因此,您可能会认为,除非您需要跨多个文档进行分组,否则最好在客户端代码中处理基本的“contenate and sort”操作。 MongoDB 目前无法在数组上“就地”执行此操作,因此客户端代码中的每个文档是您最好的选择。

但如果您确实需要对多个文档进行这种分组,那么此处显示的方法适合您。

还要注意,这里的“创建”是指创建 ObjectId 值本身,而不是来自引用对象的其他属性。如果您需要这些,那么您可以在聚合或查询之后对 id 值执行填充,当然还可以在客户端代码中进行排序。

【讨论】:

  • 感谢您的回答!遇到一些麻烦,我可能做错了什么 - 结合起来为我返回null。请查看问题更新。
  • @danm07 请确保您匹配的内容实际上包含所有数组。您可以使用$ifNull 包装每个元素,以返回一个不存在的空数组。也松开之前的$project。无论如何,它没有任何用处,可能是你的 SQL 思维让你认为你需要它。添加 $ifNull 包装作为示例。
  • 我想的也差不多。我正在尝试更新架构 -.-' 出于好奇,您知道 Mongoose 是否会在我对其进行更改时自动更新其架构,还是我需要手动更新架构?
  • @danm07 代码更改始终需要重新启动应用程序。与猫鼬无关,但与一般编译器无关。
猜你喜欢
  • 2019-10-25
  • 1970-01-01
  • 2014-04-08
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
相关资源
最近更新 更多