sql >> Databáze >  >> NoSQL >> MongoDB

Vztah Mongodb 1to1 mezi vnořenými dokumenty

S ohledem na "odsazení", které ve výpisu používám, to může ve skutečnosti vypadat déle než to, co děláte, ale ve skutečnosti tomu tak není.

Toto je další opravdu dobrý příklad použití $ mapa dostupné pro MongoDB 2.6 a vyšší. Stále existuje určité použití $unwind , ale „odvíjená“ pole mají ve skutečnosti vždy jen jedno prvek v nich. Takže prosím odpusťte můj "Highlander" reference, kterým jsem nemohl odolat :)

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

])

Takže konečný výsledek by byl:

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

Vím, že jste požádali o "žádné změny schématu", ale ve skutečnosti ne o změnu schématu, abyste řekli, že je dobrý nápad ponechat si id hodnoty zde konzistentního typu. V současné době v tomto procesu mícháte celá čísla a řetězce (doufám, že je to jen příklad), což není dobrý nápad.

Existuje tedy určitý "omezený casting", který je ve skutečnosti dostupný a který je zde použit pomocí $substr Vaše skutečné řešení se však může lišit v tom, jak to skutečně udělat. Důrazně doporučuji opravit data, pokud opravdu potřebují opravu.

V každém případě je to docela skvělé využití pro $ mapa




  1. Kde je AccountKey for CosmosDB v Azure Portal

  2. MongoDB &Meteor - Dotaz k vložení do vnořeného pole nefunguje, nebyla vyvolána žádná chyba

  3. jak dotazovat podřízené objekty v mongodb

  4. Práce s PTVS, IronPython a MongoDB