子文档之间的Mongodb 1to1关系 [英] Mongodb 1to1 relation among subdocuments

查看:59
本文介绍了子文档之间的Mongodb 1to1关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个庞大的集合,其中每个文档都有子文档,这些子文档之间具有关系.我的架构如下:

I have a huge collection where each document has subdocuments that have relations among them. My schema looks like this:

{
    userName: "user44",
    userID: "44",
    posts : [
        ...
        {
            title : "post1",
            id : "123"
            ...
        },
        {
            title : "post2",
            id : "124"
            ...
        },
        ...
    ],
    comments: [
        ...
        {
            id: 1910,
            postId : "123",
            title : "comment1",
            comment : "some comment",
            user: "user13"
        },
        {
            id: 1911,
            postId : "124",
            title : "comment2",
            comment : "some comment",
            user: "user22"
        },
        ...
    ], 
    commentUpvotes: [
        ...
        {
            id : 12,
            commentId : "1910",
            upvotedBy: "user91"
        },
        {
            id: 13,
            commentId : "1910",
            upvotedBy: "user92"
        },
        ...
    ]
}

尽管这与我的数据库无关,但原始架构与上面的完全相同.因此,上面的示例是一个用户集合,我在其中存储用户的postscomments由其他用户撰写的帖子,commentUpvotes用于存储有关谁投票的信息.不要考虑其设计的逻辑,也不要建议其他任何模式.

Although this has nothing to do with my database, original schema is exactly as above. So, this example above is a user collection, where I store posts of the user; comments that made to the posts by other users, commentUpvotes to store information about who upvoted. Don't think about the logic of its design, and don't please suggest any other schema.

问题:db.users.find({"commentUpvotes.id" : 12})应该返回此集合,但仅带有此推荐意见的comment(1910)和post(123).我用$ unwinding解决了它,这导致了性能问题.因此,建议不要解决就解决它.有什么想法吗?

Question: db.users.find({"commentUpvotes.id" : 12}) should return this collection, but only with the comment(1910) and post(123) that this upvote made to. I solved it with $unwinding which caused performance problems. Therefore please suggest to solve it without unwinding. Any ideas on that?

推荐答案

考虑到我在清单中使用的缩进",它实际上看起来比您正在做的要长,但实际上不是.

Considering the "indentation" I am using in the listing, this may actually look longer than what you are doing, but really it isn't.

这是使用 $map (适用于MongoDB 2.6及更高版本). $unwind ,但是展开"的数组实际上只包含一个元素.因此,请原谅我的 "Highlander" 无法抗拒:)

This is a another really good example of using $map as available to MongoDB 2.6 and greater. There is still some use of $unwind, but the arrays being "unwound" actually only ever have one element in them. So please forgive my "Highlander" references which I could not resist :)

db.users.aggregate([

    // Match your document or documents
    { "$match": {
        "commentUpvotes.id": 12
    }},

    // Get the one "up-votes" entry that matches
    { "$project": {
        "posts": 1,
        "comments": 1,
        "commentUpVotes": {
            "$setDifference": [
                { 
                    "$map": {
                        "input": "$commentUpvotes",
                        "as": "el",
                        "in": {
                            "$cond": [
                                { "$eq": [ "$$el.id", 12 ] },
                                "$$el",
                                false
                            ]
                        }  
                    }
                },
                [false]
            ]
        }
    }},

    // There is only one!
    { "$unwind": "$commentUpVotes" },

    // Get the one comments entry that matches
    { "$project": {
        "posts": 1,
        "comments": {
            "$setDifference": [
                { 
                    "$map": {
                        "input": "$comments",
                        "as": "el",
                        "in": {
                            "$cond": [
                                { 
                                    "$eq": [ 
                                        { "$substr": [ "$$el.id", 0, 4 ] }, 
                                        "$commentUpVotes.commentId"
                                    ] 
                                },
                                "$$el",
                                false
                            ]
                        }  
                    }
                },
                [false]
            ]
        },
        "commentUpVotes": 1
    }},

    // And there is only one!
    { "$unwind": "$comments" },

    // Get the one post that matches
    { "$project": { 
        "posts": {
            "$setDifference": [
                { 
                    "$map": {
                        "input": "$posts",
                        "as": "el",
                        "in": {
                            "$cond": [
                                { 
                                    "$eq": [ 
                                        "$$el.id", 
                                        "$comments.postId"
                                    ] 
                                },
                                "$$el",
                                false
                            ]
                        }  
                    }
                },
                [false]
            ]
        },
        "comments": 1,
        "commentUpVotes": 1
    }},

    // Optionally group back to arrays. There can be only one!
    { "$group": {
        "_id": "$_id",
        "posts": { "$first": "$posts" },
        "comments": { "$push": "$comments" },
        "commentUpVotes": { "$push": "$commentUpVotes" }
    }}

])

因此最终结果将是:

{
    "_id" : ObjectId("539065d3cd0f2aac5f55778e"),
    "posts" : [
            {
                    "title" : "post1",
                    "id" : "123"
            }
    ],
    "comments" : [
            {
                    "id" : 1910,
                    "postId" : "123",
                    "title" : "comment1",
                    "comment" : "some comment",
                    "user" : "user13"
            }
    ],
    "commentUpVotes" : [
            {
                    "id" : 12,
                    "commentId" : "1910",
                    "upvotedBy" : "user91"
            }
    ]
}

我知道您要求不更改模式",但实际上并不需要更改模式,这表示将id值保持在此处为一致类型是个好主意.当前,您正在此过程中混合使用整数和字符串(我希望这只是一个示例),这不是一个好主意.

I know you asked for "no schema changes", but not really a schema change to say it is a good idea to keep your id values here of a consistent type. Currently you are mixing Integers and strings in this process ( I hope it's just an example ) which is not a good idea.

因此,这里使用 $substr ,但是您实际的解决方案可能会因实际执行方式而异.我强烈建议修复确实需要修复的数据.

Thus there is some "limited casting" that actually is available employed here using $substr, however your actual solution may vary in how to really do this. I strongly suggest fixing the data if it really does need fixing.

无论如何, $map

这篇关于子文档之间的Mongodb 1to1关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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