2016-09-29 46 views
0

我有一个JSON文档这样MongoDB中:更新嵌套的对象,如果它存在,否则它添加

{ "_id" : ObjectId("57ed88c0965bedd2b11d5727"), 
    "refid" : 2, 
    "votes" : [ 
    { "ip" : "127.0.2.1", "rating" : 5 }, 
    { "ip" : "127.0.3.1", "rating" : 2 }, 
    { "ip" : "127.59.83.210", "rating" : 50 }, 
    { "ip" : "127.56.26.191", "rating" : 5 }, 
    { "ip" : "127.59.83.210", "rating" : 5 }, 
    { "ip" : "127.59.83.210", "rating" : 30 } 
    ] 
} 

而不是创建每个IP愚弄,我想更新发现如果记录IP存在,或者如果不存在,则添加新条目。关于如何做类似的操作有很多问题,但没有一个我可以找到确切的问这个简单的问题。我试图在Node.js中:

db.collection('ratings').update({ "refid":refid, "votes.ip":ip }, 
    { 
    $push: { votes: { "ip":ip, "rating":rating } 
    } 
}) 

但它只是不断增加新的条目,当我从同一个IP投票。

注意:我没有使用猫鼬。

如果我的问题过于简单,我很抱歉,我对MongoDB很陌生。我只是想知道是否有一种很好的方法可以做到这一点,而不是以编程方式迭代“投票”中的每个记录。谢谢!

编辑:我所要求的是目前不可能的,我在正确的下方标记了一个答案,其中包含解释和指向MongoDB票证的链接以增强功能。

至于我在这里的问题的场景,下面的代码适用于我。我不知道它有多好或坏的表现是明智的,但它涵盖了所有这些场景:

  • 如果记录不存在可言,如果记录存在创建
  • ,寻找IP,如果找到,更新评级
  • 如果记录存在,但IP不,插入一个新的评价

作品:

db.collection('ratings').findOne({ "refid":refid }).then(function(vote) { 
    if (vote == null) { 
    newrating = {refid: refid, votes: [{ ip: ip, rating: rating }]}; 
    db.collection('ratings').save(newrating); 
    } else { 
    db.collection('ratings').findOne({ "refid":refid, "votes.ip":ip }).then(function(rate) { 
     if (rate != null) { 
     db.collection('ratings').update(
      { refid: refid, "votes.ip" : ip }, 
      { $set: { "votes.$.rating" : rating } } 
     ) 
     } else { 
     db.collection('ratings').update({"refid":refid,"votes.ip" : {$ne : ip }}, 
      { $push: { votes: { "ip" : ip, "rating" : rating, }}} 
     ) 
     } 
    }) 
    } 
}) 
+0

貌似重复这样的:http://stackoverflow.com/questions/14527980/can-you-specify-a- key-for-addtoset-in-mongo – a0viedo

+0

就我所见,评论中的链接和后续问题都不包含我的场景;只有如何防止基于密钥的更新,以及单独如何在密钥不存在的情况下如何添加记录。它不包括以下情况:如果有更新,则另外添加。 –

回答

2

要插入文档如果不存在由upsert完成,并且如果要更新条件嵌入式文档,则需要$位置运算符。所以你需要在查询中使用它们来实现上述功能。

但现在的MongoDB不支持与$位置操作upserting

不要使用UPSERT操作位置操作$因为, 刀片将在插入使用$作为一个字段名文件。

所以你想要的是不可能在一个查询现在做,或者你可以做两个查询。

首先

db.collection('ratings')).update(
    {"refid":refid, "votes.ip": ip}, 
    { 
    $set: { "votes.$.rating":rating } 
    } 
) 

它返回的更新文件的数量,如果是1就很好,如果它是你需要按新的记录0。

db.collection('ratings')).update({ "refid":refid, "votes.ip":{$ne: ip}}, 
    {$push: { votes: { "ip":ip , "rating":rating }} 
}) 

还有对位置运营商和upserting JIRA票,PLZ投票这个问题,如果你想在MongoDB中此功能。下面是它可能用此方式解决以及问题

https://jira.mongodb.org/browse/SERVER-3326

+0

谢谢。 Puneet,我将用最适合我的代码编辑原始帖子,但将你的标记标记为正确的答案,因为这是一个精确的解释,为什么它不可能。谢谢! –

0

也许

db.collection('ratings').update({ "refid":refid, "ip":ip }, 
    { 
     $addToSet: { votes: { "ip":ip, "rating":rating } 
    } 
}) 
0

试试这个

db.collection('ratings')).update({ "refid":refid, "votes.ip":ip , "votes.rating":{$ne: rating }}, 
    {$push: { votes: { "ip":ip , "rating":rating }} 
}) 

它会增加新的记录,如果等级不存在对于给定的IP,并在记录被存在给IP和评价则没有重复的记录添加。

0

的链接。这是我用于工作的一个。

拉出的匹配值,推动如下新值:

db.collection(‘ratings’).update({“refid”:refid}, 
     {$pull: {votes: {“ip": ip}}}, 
    {multi: true}); 

db.collection("ratings").update({“refid":refid}, 
    {$push:{‘votes’:{"ip":ip,"rating":rating}}}) 
相关问题