sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongodb 1to1 relation mellan underdokument

Med tanke på "indraget" jag använder i listan kan detta faktiskt se längre ut än vad du gör, men det är det verkligen inte.

Detta är ett annat riktigt bra exempel på hur man använder $ karta som tillgänglig för MongoDB 2.6 och senare. Det finns fortfarande en viss användning av $unwind kod> , men de arrayer som "lindas upp" har faktiskt bara en element i dem. Så förlåt min "Highlander" referenser som jag inte kunde motstå :)

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

])

Så slutresultatet skulle bli:

{
    "_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"
            }
    ]
}

Jag vet att du bad om "inga schemaändringar", men egentligen inte en schemaändring för att säga att det är en bra idé att behålla ditt id värden här av konsekvent typ. För närvarande blandar du heltal och strängar i den här processen (jag hoppas att det bara är ett exempel) vilket inte är en bra idé.

Det finns alltså en del "begränsad casting" som faktiskt är tillgänglig här med strong>$substr , men din faktiska lösning kan variera i hur du verkligen gör detta. Jag rekommenderar starkt att du fixar data om den verkligen behöver fixas.

Hur som helst, en ganska cool användning för $ karta




  1. Ej auktoriserad för fråga på admin.system.namespaces på mongodb

  2. MongoDB listCollections filter

  3. MongoDB datum och tidsvärde lagras inte korrekt

  4. Atomic om det inte finns, sätt in Mongodb .Net-drivrutinen