Mongoose 聚合匹配 objectIds 数组

Posted

技术标签:

【中文标题】Mongoose 聚合匹配 objectIds 数组【英文标题】:Mongoose Aggregation match an array of objectIds 【发布时间】:2016-10-14 00:45:18 【问题描述】:

我有一个看起来像这样的架构

var Post = new mongoose.Schema(
    author: 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    ,
    created: 
        type: Date,
        Default: Date.now
    )

我也有一个用户表。我有一组用户 ID,我正在尝试根据一组用户 ID 搜索帖子表

举例

var userIds = ["575e96652473d2ab0ac51c1e","575e96652473d2ab0ac51c1d"] .... and so on 

我想返回这些用户创建的所有帖子。帖子应按创建日期排序。有没有办法根据提供的用户 ID 对帖子进行分组,基本上匹配单个用户的帖子?

我想要达到的结果是这样的:

 [
    userAId : "56656.....",
    post : [postA, postB],
   , 
    userBId :"12345...", 
    post : [postA, postB]
]

如何编写此查询?

这是我目前所拥有的

Post.aggregate([
  // "$unwind" : "",
    // "$group": 
    //     _id: "$author",
    //     "created" : "$sum" : 1 
    // 
    "$match" :  author : id
]).exec(function(error, data) 
  if(error)
    return console.log(error);
  else
    return console.log(data)
  
)




    "_id" : ObjectId("575e95bc2473d2ab0ac51c1b"),
    "lastMod" : ISODate("2016-06-13T11:15:08.950Z"),
    "author" : ObjectId("575dac62ec13010678fe41cd"),
    "created" : ISODate("2016-06-13T11:15:08.947Z"),
    "type" : "photo",
    "end" : null,
    "commentCount" : 0,
    "viewCount" : 0,
    "likes" : 0,
    "tags" : [],
    "title" : "Today is a good day",
    "__v" : 0

【问题讨论】:

你能从 mongo 发布完整的帖子文档吗? 你的意思是发布整个帖子文档的架构吗?? db.post.findOne() 没问题 - 请删除敏感信息 "_id" : ObjectId("575e95bc2473d2ab0ac51c1b"), "lastMod" : ISODate("2016-06-13T11:15:08.950Z"), "author" : ObjectId("575dac62ec13010678fe41cd"), “创建”:ISODate(“2016-06-13T11:15:08.947Z”),“类型”:“照片”,“结束”:null,“commentCount”:0,“viewCount”:0,“喜欢”: 0, "tags" : [ ], "title" : "今天是个好日子", "__v" : 0 【参考方案1】:

要返回由 id 列表中描述的用户创建的所有帖子,请在查询中使用 $in 运算符,然后将 sort() 方法链接到按创建日期字段对结果进行排序的查询:

Post.find( "author":  "$in": userIds  )
    .sort("-created") // or .sort( field: 'asc', created: -1 );
    .exec(function (err, data)
        if(err)
            return console.log(err);
         else 
            return console.log(data);
        
    );

要获得每个用户对帖子 ID 进行分组的结果,您需要运行以下聚合操作:

Post.aggregate([
     "$match" :  "author":  "$in": userIds   ,
     "$sort":  "created": -1  ,
    
        "$group" : 
            "_id" : "$author",
            "posts" :  "$push": "$_id" 
        
    ,
    
        "$project": 
            "_id": 0,
            "userId": "$_id",
            "posts": 1
        
    
]).exec(function (err, result)
    if(err)
        return console.log(err);
     else 
        return console.log(result);
    
);

或者使用流畅的 API:

 Post.aggregate()
    .match( "author":  "$in": userIds  )
    .sort("-created")
    .group(
        "_id" : "$author",
        "posts" :  "$push": "$_id" 
     )
    .project(
        "_id" : 0,
        "userId" : "$_id",
        "posts": 1
     )
    .exec(function (err, result)
        if(err)
            return console.log(err);
         else 
            return console.log(result);
        
    );

【讨论】:

有没有办法根据提供的用户 ID 对这篇文章进行分组??基本上匹配这样的个人用户的帖子。 userAId:“56656”,帖子:[postA,postB],userBId:“xys”,帖子:[postA,postB] 从数据库中获取帖子并在代码中进行连接会更好吗? @user3412942 你能否更新你的问题,因为原来的问题我想返回这些用户创建的所有帖子。帖子应按创建日期排序。我该如何编写这个查询? 解决了,不是吗?请记住,当已有答案时,在 SO 上更改您的问题被认为是不好的做法 - chameleon questions 抱歉,我已经更新了问题,非常感谢您的支持。 您先生是钻石,这正是我所需要的。对于所有的支持和耐心来说,这已经足够了。【参考方案2】:

这在没有聚合的情况下应该是可能的。

Post
.find( author:  $in: userIds  )
.sort( created: -1 )

如果您收到 CastError: Cast to ObjectId failed,请确保将您的 userIds 数组从字符串数组映射到 mongoose id 数组。

userIds = userIds.map(userId => new mongoose.Types.ObjectId(userId))

【讨论】:

有没有办法根据提供的用户 ID 对这篇文章进行分组??基本上匹配这样的个人用户的帖子。 userAId:“56656”,帖子:[postA,postB],userBId:“xys”,帖子:[postA,postB]

以上是关于Mongoose 聚合匹配 objectIds 数组的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb - 解决 ( aggregate聚合管道 ) $match 根据 id 匹配 返回 [ ] 的问题

mongodb聚合匹配属性

与 mongoDb 和 mongoose 聚合后填充单个 ObjectId 引用

MongoDB - 在 ObjectId 上聚合 $match

Mongoose 按标签聚合分组项目

Mongoose:通过聚合获取对象数组的大小