代码之家  ›  专栏  ›  技术社区  ›  ᴄʀᴏᴢᴇᴛ

mongodb在push之前聚合修改元素

  •  0
  • ᴄʀᴏᴢᴇᴛ  · 技术社区  · 7 年前

    我尝试使用mongodb对mongodb进行聚合查询。

    以下是我查询的文档的简化版本:

    {
        "_id" : ObjectId("574edf0ece8300c95ae0a1a4"),
        "user" : {
            "$ref" : "User",
            "$id" : ObjectId("574eac76ce8300a251e0a1a4"),
            "$db" : "master"
        },
        "content" : "some text",
        "hash" : "f46fe1003204704ce11edb15ff4b0ca3f93232da",
        "servicesToPublish" : [ 
            {
                "serviceTokenId" : "53931163ce830032106dfa6f",
                "status" : "published",
                "statusUpdatedAt" : ISODate("2016-06-01T13:12:17.000Z"),
                "type" : "text"
            }
        ]
    }
    

    以下是我使用的查询:

    $aggregationBuilder
        ->match()
            ->field('servicesToPublish.status')->equals(ServiceToPublish::STATUS_PUBLISHED)
            ->field('user.$id')->in($userIds)
        ->group()
            ->field('_id')->expression('$hash')
            ->field('posts')->push($aggregationBuilder->expr()->ifNull('$servicesToPublish', '[]'))
            ->field('users')->push('$users')
    ;
    

    转化为mongo查询:

    db.message.aggregate([{
        "$match": {
            "servicesToPublish.status": "published",
            "user.$id": {
                "$in": [ObjectId("5a733013ce8300b566d15a9b"),...]
            }
        }
    }, {
        "$group": {
            "_id": "$hash",
            "posts": {"$push": "$servicesToPublish"},
            "users": {"$push": "$user"}
        }
    }]);
    

    这是一个示例结果

    {
        "_id" : "19a5a9315ba8ac5ffb3779e68b887c805c61d54c",
        "posts" : [ 
            [ 
                {
                    "serviceTokenId" : "5a7abe9cce8300c502f38d6c",
                    "type" : "text",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T08:20:02.000Z")
                }, 
                {
                    "serviceTokenId" : "59c14d0ece83008449843d15",
                    "type" : "other",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T08:20:04.000Z")
                }
            ], 
            [ 
                {
                    "serviceTokenId" : "59c13700ce83005a66843d15",
                    "type" : "text",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T06:21:57.000Z")
                }, 
                {
                    "serviceTokenId" : "59c13725ce83005668843d15",
                    "type" : "other",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T06:21:59.000Z")
                }
            ]
        ],
        "user" : [ 
            {
                "$ref" : "User",
                "$id" : ObjectId("5a733013ce8300b566d15aa4"),
                "$db" : "master"
            }, 
            {
                "$ref" : "User",
                "$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
                "$db" : "master"
            }
        ]
    }
    

    user posts ,是否有一种方法可以将用户id用作post数组中的键(类似于: "posts": {"id1":[...], "id2": [...]} )或者像这样将用户id添加到posts数组的每个元素中 {"userId":"...", "serviceTokenId" : "...","type":"...", "status":"...", "statusUpdatedAt":ISODate("...")}


    如果没有办法做到这一点,我是否可以确定posts数组的顺序将与user数组的顺序相同?(即 帖子 对应于 用户 )

    1 回复  |  直到 7 年前
        1
  •  1
  •   Alex Blex    7 年前

    你可以用新的 $addFields 将用户添加到帖子的阶段。

    在纯monngodb查询中,它将如下所示:

    db.message.aggregate([
    {
        "$match": {
            "servicesToPublish.status": "published",
            "user.$id": {
                "$in": [ObjectId("5a733013ce8300b566d15a9b"),...]
            }
        }
    }, 
    {
        "$addFields" : { servicesToPublish: { $map: { 
            input: "$servicesToPublish", 
            as: "service", 
            in: { $mergeObjects: [ "$$service", { user: "$user" } ] }
        } } }
    },
    {
        "$group": {
            "_id": "$hash",
            "posts": {"$push": "$servicesToPublish"},
            "user": {"$push": "$user"}
        }
    }
    ]);
    

    它应该给你这样的东西:

    {
        "_id" : "19a5a9315ba8ac5ffb3779e68b887c805c61d54c",
        "posts" : [ 
            [ 
                {
                    "serviceTokenId" : "5a7abe9cce8300c502f38d6c",
                    "type" : "text",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T08:20:02.000Z"),
                    "user" : {
                        "$ref" : "User",
                        "$id" : ObjectId("5a733013ce8300b566d15aa4"),
                        "$db" : "master"
                    }
                }, 
                {
                    "serviceTokenId" : "59c14d0ece83008449843d15",
                    "type" : "other",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T08:20:04.000Z")
                    "user" : {
                        "$ref" : "User",
                        "$id" : ObjectId("5a733013ce8300b566d15aa4"),
                        "$db" : "master"
                    }
                }
            ], 
            [ 
                {
                    "serviceTokenId" : "59c13700ce83005a66843d15",
                    "type" : "text",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T06:21:57.000Z")
                    "user" : {
                        "$ref" : "User",
                        "$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
                        "$db" : "master"
                    }
                }, 
                {
                    "serviceTokenId" : "59c13725ce83005668843d15",
                    "type" : "other",
                    "status" : "published",
                    "statusUpdatedAt" : ISODate("2018-04-17T06:21:59.000Z")
                    "user" : {
                        "$ref" : "User",
                        "$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
                        "$db" : "master"
                    }
                }
            ]
        ],
        "user" : [ 
            {
                "$ref" : "User",
                "$id" : ObjectId("5a733013ce8300b566d15aa4"),
                "$db" : "master"
            }, 
            {
                "$ref" : "User",
                "$id" : ObjectId("5a7abc2ece83003b6af38d6c"),
                "$db" : "master"
            }
        ]
    }
    

    $ 在字段名中。像这样使用它的尝试 { $mergeObjects: [ "$$services", { userId: "$user.$id" } ] } results with error 16410“字段路径字段名不能以“$”开头。”

    推荐文章