首页 文章

MongoDB - 涉及列表的upsert

提问于
浏览
5

我是一个MongoDB新手,想问一下如何写一个涉及upsert和list的更新命令 .

基本上我想完成这样的事情:

{"_id" : ObjectId("4c28f62cbf8544c60506f11d"),
"some_other_data":"goes here",
"trips": [
    {"name": "2010-05-10",
     "loc": [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
        {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}]
    },
    {"name": "2010-05-08",
     "loc": [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"},
        {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
        {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}]
    }
]}

注意:

  • 您提供旅行名称和当前位置

  • 如果旅程不存在,则需要创建

  • trips.name应该是唯一的,以便如果它存在,则追加到位置数组

这是我写的结合了位置运算符和$ push的查询 .

db.mycollection.update({"application_id": "MyTestApp", 
                            "trips.name": "2010-05-10"},
                           {$push: {'trips.$.loc': {"lat":11, "lng":11} }}, 
                           true);

但这会产生如下数据:

> db.mycollection.find({"application_id":"MyTestApp"})          
{ "_id" : ObjectId("4c29044ebf8544c60506f11f"), 
"application_id" : "MyTestApp", 
"trips" : { "$" : { "loc" : [ { "lat" : 11, "lng" : 11 } ] }, 
"name" : "2010-05-10" } 
}

你可以看到

  • "trips"不是数组

  • 它按字面意思"$"并用它创建了一个键(doh!)

到目前为止,我对MongoDB非常满意,但是编写复杂的查询肯定会有一个陡峭的学习曲线 .

任何反馈将不胜感激 .

提前谢谢,Amie

2 回答

  • 4

    你不能混合位置运算符(“$”)和upsert;在插入期间,“$”将被视为字段名称 . 您不能对新文档执行此操作,只能对现有文档执行此操作 .

    我建议了一个更像这样的结构:

    {"_id" : ObjectId("4c28f62cbf8544c60506f11d"),
    "some_other_data":"goes here",
    "trips": { 
        "2010-05-10":
           [{"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:35"}, 
            {"lat":21.321231, "lng": 16.8783234, "updated_at": "Mon May 10 2010 15:24:24"}],
        "2010-05-08": 
           [{"lat":21.324239, "lng": 16.8735234, "updated_at": "Mon May 8 2010 11:18:05"},
            {"lat":21.311234, "lng": 16.8743271, "updated_at": "Mon May 8 2010 11:17:55"}, 
            {"lat":21.321238, "lng": 16.8782219, "updated_at": "Mon May 8 2010 11:17:45"}]
        }
    }
    

    然后你可以发布这样的更新:

    db.mycollection.update({application_id: "MyTestApp", "trips.2010-05-10":{$exists:true}},
                           {$push: {"trips.2010-05-10": {lat:11, lng:11} }}, 
                           true);
    

    导致插入此结果 .

    > db.mycollection.find()
    { "_id" : ObjectId("4c2931d17b210000000045f0"), 
        "application_id" : "MyTestApp", 
        "trips" : { "2010-05-10" : [ { "lat" : 11, "lng" : 11 } ] } }
    

    并再次运行它给你这个:

    > db.mycollection.find()
    { "_id" : ObjectId("4c2932db7b210000000045f2"), 
        "application_id" : "MyTestApp", 
        "trips" : { "2010-05-10" : 
            [ { "lat" : 11, "lng" : 11 }, 
              { "lat" : 11, "lng" : 11 } ] } }
    
  • 1

    EDITED TO INCLUDE CORRECT SOLUTION

    这正是我学习Mongo的问题 - 你正在寻找与 update 命令一起使用的 $addToSet 运算符(see docs here),以及你正在使用的 $ 位置运算符 .

    $ addToSet {$ addToSet:{field:value}}仅当数组不在数组中时才向数组添加值 .

    因此查询变为(db.stack是我用于测试目的的集合),示例运行如下:

    db.stack.update({ "trips.name":"2010-05-10" }, 
                    { $addToSet: { "trips.$.loc":{"lat":11, "lng":12} } }
                   );
    

    TEST RUN(带有一些不重要元素空间的缩写):

    #### YOUR ITEM IN THE DB
    > db.stack.find({"trips.name":"2010-05-10"})
    { "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here", 
        "trips" : [
        { "name" : "2010-05-10",
            "loc" : [ {
                    "lat" : 21.321231,
                    "lng" : 16.8783234,
                    "updated_at" : "Mon May 10 2010 15:24:35"
                }, { "lat" : 21.321231,
                    "lng" : 16.8783234,
                    "updated_at" : "Mon May 10 2010 15:24:24"
                } ] },
        { "name" : "2010-05-08",
            "loc" : [ ... ]
        } ] }
    #### SUCCESSFULLY ADDS ITEM TO PROPER ARRAY
    > db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":11}}});
    > db.stack.findOne()
    { "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here",
        "trips" : [
            { "loc" : [
                    { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:35"
                    }, { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:24"
                    }, { "lat" : 11,
                        "lng" : 11
                    }
                ], "name" : "2010-05-10"
            },
            { "name" : "2010-05-08",
                "loc" : [ ...  ]
            } ] }
    #### ON REPEAT RUN DOESN'T ADD NEW ELEMENT
    > db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":11}}});
    > db.stack.findOne()
    { "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here",
        "trips" : [ {
                "loc" : [
                    { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:35"
                    }, { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:24"
                    }, { "lat" : 11,
                        "lng" : 11
                    }
                ], "name" : "2010-05-10"
            },
            { "name" : "2010-05-08",
                "loc" : [ ...  ]
            } ] }
    #### BUT WILL CORRECTLY ADD ANOTHER ELEMENT TO THE SAME ARRAY IF IT'S NOT PRESENT
    > db.stack.update({"trips.name":"2010-05-10"}, {$addToSet: {"trips.$.loc":{"lat":11, "lng":12}}});
    > db.stack.findOne()
    { "_id" : ObjectId("4c28f62cbf8544c60506f11d"), "some_other_data" : "goes here",
        "trips" : [
            { "loc" : [
                    { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:35"
                    }, { "lat" : 21.321231,
                        "lng" : 16.8783234,
                        "updated_at" : "Mon May 10 2010 15:24:24"
                    }, { "lat" : 11,
                        "lng" : 11
                    }, { "lat" : 11,
                        "lng" : 12
                    }
                ], "name" : "2010-05-10"
            },
            { "name" : "2010-05-08",
                "loc" : [ ... ]
        } ] }
    

相关问题