如果存在,请更新MongoDB中的嵌套对象,否则添加它 [英] Update nested object in MongoDB if it exists, otherwise add it

查看:145
本文介绍了如果存在,请更新MongoDB中的嵌套对象,否则添加它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在mongoDB中有一个像这样的json文档:

I've got a json doc like this in 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中尝试此操作:

And instead of creating dupes per IP, I want to update the record found if the IP exists, or add a new entry if it doesn't. There are tons of questions on how to do similar operations, but none that I could find exactly asking something this simple. I am trying this in Node.js:

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

但是当我从同一IP投票时,它只会不断添加新条目.

But it just keeps adding new entries when I vote from the same IP.

注意::我不使用猫鼬.

我很抱歉,如果我的问题过于基础,我对MongoDB还是陌生的.我只是想知道是否有一个很好的方法来完成此任务,而不是以编程方式遍历投票"中的每条记录.谢谢!

I apologize if my question is overly elementary, I'm pretty new to MongoDB. I'm just wondering if there's a good way to do this baked in rather than iterating through every record in "votes" programmatically. Thanks!

编辑:我目前无法提出要求,我在下方标记了一个正确的答案,其中包含解释和指向MongoDB的票证链接以进行增强.

What I'm asking isn't currently possible, I've marked an answer below correct which contains the explanation and a link to a ticket at MongoDB for an enhancement.

至于我在此问题中的情况,下面的代码对我有用.我不知道在性能方面有多好,但它涵盖了所有这些情况:

As for the scenario in my question here, the code below works for me. I have no idea how good or bad it is performance wise, but it covers all of these scenarios:

  • 如果记录根本不存在,请创建它
  • 如果记录存在,请查找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, }}}
        )
      }
    })
  }
})

推荐答案

要插入文档(如果不存在)是通过upsert完成的,如果要更新条件嵌入式文档,则需要$位置运算符.因此,您需要在查询中同时使用两者来实现上述功能.

To insert a document if not exist is done by upsert and if you want to update a conditional embedded document you need $ positional operator. So you need to use both in query to implement above functionality.

但是现在mongodb不支持使用$位置运算符进行加粗

请勿将位置运算符$与upsert操作一起使用,因为, 插入将使用$作为插入文档中的字段名称.

Do not use the positional operator $ with upsert operations because, inserts will use the $ as a field name in the inserted document.

因此,您目前无法在一个查询中执行此操作,或者您可以在两个查询中执行操作.

第一

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

它返回更新的文档数,如果为1则可以,如果为0,则需要推送新记录.

It returns the number of documents updated, if it is 1 it's fine, and if it is 0 you need to push new record.

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

还有jira用于位置运算符和upserting的票证,如果您希望在mongodb中使用此功能,请plz投票给该问题.以下是问题的链接

There also jira ticket for positional operator and upserting, plz vote for this issue if you want this functionality in mongodb. Below is the link of issue

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

这篇关于如果存在,请更新MongoDB中的嵌套对象,否则添加它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆