MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Mongodb 1to1 relazione tra documenti secondari

Considerando il "rientro" che sto usando nell'elenco, questo potrebbe effettivamente sembrare più lungo di quello che stai facendo, ma in realtà non lo è.

Questo è un altro ottimo esempio di utilizzo di $map come disponibile per MongoDB 2.6 e versioni successive. È ancora possibile utilizzare $unwind , ma gli array "svolti" in realtà ne hanno solo uno elemento in essi. Quindi, per favore, perdona il mio "Highlander" riferimenti a cui non ho resistito :)

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

])

Quindi il risultato finale sarebbe:

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

So che hai chiesto "nessuna modifica allo schema", ma non proprio una modifica allo schema per dire che è una buona idea mantenere il tuo id valori qui di un tipo coerente. Attualmente stai mescolando interi e stringhe in questo processo (spero sia solo un esempio), il che non è una buona idea.

Quindi c'è un "casting limitato" che è effettivamente disponibile qui impiegato usando $substr , tuttavia la tua soluzione effettiva può variare nel modo in cui farlo davvero. Suggerisco vivamente di correggere i dati se è davvero necessario ripararli.

In ogni caso, un utilizzo piuttosto interessante per $map