MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Relação Mongodb 1to1 entre subdocumentos


Considerando o "recuo" que estou usando na listagem, isso pode parecer mais longo do que você está fazendo, mas na verdade não é.

Este é outro bom exemplo de uso de $ mapa conforme disponível para o MongoDB 2.6 e superior. Ainda há algum uso de $unwind , mas os arrays sendo "desenrolados" na verdade só têm um elemento neles. Então, por favor, perdoe meu "Highlander" referências a que não resisti :)
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" }
    }}

])

Então o resultado final seria:
{
    "_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"
            }
    ]
}

Eu sei que você pediu "sem alterações de esquema", mas não é realmente uma alteração de esquema para dizer que é uma boa ideia manter seu id valores aqui de um tipo consistente. Atualmente você está misturando Integers e strings neste processo (espero que seja apenas um exemplo) o que não é uma boa ideia.

Assim, há algum "cast limitado" que realmente está disponível empregado aqui usando $substr , no entanto, sua solução real pode variar em como realmente fazer isso. Eu sugiro fortemente a correção dos dados se realmente precisar de correção.

De qualquer forma, um uso muito legal para $ mapa