sql >> Database >  >> NoSQL >> MongoDB

Mongodb 1op1 relatie tussen subdocumenten

Gezien de "inspringing" die ik in de lijst gebruik, lijkt dit misschien langer dan wat u doet, maar dat is het niet.

Dit is weer een heel goed voorbeeld van het gebruik van $map zoals beschikbaar voor MongoDB 2.6 en hoger. Er is nog steeds enig gebruik van $unwind , maar de arrays die worden "afgewikkeld" hebben eigenlijk maar één element erin. Dus vergeef mijn "Highlander" referenties die ik niet kon weerstaan ​​:)

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

])

Het eindresultaat zou dus zijn:

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

Ik weet dat je om "geen schemawijzigingen" hebt gevraagd, maar niet echt een schemawijziging om te zeggen dat het een goed idee is om je id te behouden waarden hier van een consistent type. Momenteel mix je gehele getallen en strings in dit proces (ik hoop dat het slechts een voorbeeld is), wat geen goed idee is.

Er is dus enige "beperkte casting" die hier daadwerkelijk beschikbaar is met behulp van $substr , uw werkelijke oplossing kan echter verschillen in hoe u dit echt doet. Ik raad ten zeerste aan om de gegevens te corrigeren als deze echt moeten worden gerepareerd.

In ieder geval een behoorlijk cool gebruik voor $map




  1. Hoe zoek ik strings in redis?

  2. mangoest om te bepalen dat update-upsert bezig is met invoegen of bijwerken

  3. mongodb kan geen transactie doen in Go en heeft altijd Kan geen naamruimte maken in transactie met meerdere documenten

  4. ServiceStack Entiteiten Id veldnaam