使用分层JSON进行MongoDB更新 - 如何高效?点符号?

时间:2015-08-21 06:41:44

标签: java json mongodb upsert database

Mongodb有一个更新功能,它可以增加预先存在的字段。但是,我发现它只能更新平面JSON。每当JSONObject内部有一个JSONObject时,我想要增加一个值,我实际上似乎无法做到这一点。它将返回此错误:

com.mongodb.WriteConcernException: Write failed with error code 14 and error message 
'Cannot increment with non-numeric argument: {laneQty: { BOTTOM: 1 }}'

正如你所看到的,我尝试将laneQty.BOTTOM更新递增1.我不想编写一个算法来将每个单独的json字段更改为点表示法(如laneQty.BOTTOM),所以有没有办法要么将JSON转换为点符号pre-upsert?

现在我的一般upsert函数如下所示:

public boolean incrementJson(BasicDBObject json, String colName, ArrayList<String> queryParams, ArrayList<String> removeParams){
    /*make sure the game id AND the main player id can't both be the same. 
    If either/or, it's fine. We don't want duplicates.
    */
    BasicDBObject query = new BasicDBObject();
    DBCollection collection = db.getCollection(colName);
    for(int i = 0; i < queryParams.size(); i++){
        String param = queryParams.get(i);
        query.put(param, json.get(param));
    }
    for(String param : removeParams){
        json.remove(param);
    }
    return collection.update(query, new BasicDBObject("$inc", json), true, false).isUpdateOfExisting();
}

是否有任何建议的升级代码可以轻松更新分层json?谢谢!

顺便说一句,我很难对此进行硬编码。有大量的分层对象,这将永远带我。此外,我无法完全控制在图层中填充哪些字段,因此我不能每次都说“laneQty.BOTTOM”,因为它并不总是存在。在upserting之前,BasicDBObject json实际上是一个解析为BasicDBObject的java bean。如果它有任何帮助,这是它的构造函数:

public ChampionBean(int rank, int division, int assists, int deaths, int kills, int qty, int championId,
        HashMap<String, Integer> laneQty, HashMap<String, Integer> roleQty,
        ParticipantTimelineDataBean assistedLaneDeathsPerMinDeltas,
        ParticipantTimelineDataBean assistedLaneKillsPerMinDeltas, ParticipantTimelineDataBean creepsPerMinDeltas,
        ParticipantTimelineDataBean csDiffPerMinDeltas, ParticipantTimelineDataBean damageTakenDiffPerMinDeltas,
        ParticipantTimelineDataBean damageTakenPerMinDeltas, ParticipantTimelineDataBean goldPerMinDeltas,
        ParticipantTimelineDataBean xpDiffPerMinDeltas, ParticipantTimelineDataBean xpPerMinDeltas, int wins,
        int weekDate, int yearDate) {
    super();
    this.rank = rank;
    this.division = division;
    this.assists = assists;
    this.deaths = deaths;
    this.kills = kills;
    this.qty = qty;
    this.championId = championId;
    this.laneQty = laneQty;
    this.roleQty = roleQty;
    this.assistedLaneDeathsPerMinDeltas = assistedLaneDeathsPerMinDeltas;
    this.assistedLaneKillsPerMinDeltas = assistedLaneKillsPerMinDeltas;
    this.creepsPerMinDeltas = creepsPerMinDeltas;
    this.csDiffPerMinDeltas = csDiffPerMinDeltas;
    this.damageTakenDiffPerMinDeltas = damageTakenDiffPerMinDeltas;
    this.damageTakenPerMinDeltas = damageTakenPerMinDeltas;
    this.goldPerMinDeltas = goldPerMinDeltas;
    this.xpDiffPerMinDeltas = xpDiffPerMinDeltas;
    this.xpPerMinDeltas = xpPerMinDeltas;
    this.wins = wins;
    this.weekDate = weekDate;
    this.yearDate = yearDate;
}

participantTimelineDataBean是另一个bean,里面有4个int字段。我想增加这些字段(所以是的,它只有2层深,所以如果有一个2层深层可用性的解决方案,我也会采用它。)

2 个答案:

答案 0 :(得分:0)

使用点符号:

 new BasicDBObject("$inc", new BasicDBObject("laneQty.BOTTOM", 1) )

替代快速和彻底的解决方案:只需collection.save整个文档_id下。

答案 1 :(得分:0)

使用此库:

https://github.com/rhalff/dot-object

例如,如果您有这样的对象:

var jsonObject = {
  info : {
    firstName : 'aamir',
    lastName : 'ryu'
    email : 'aamiryu@gmail.com'
  },
}

那么你的node.js代码就像这样:

var dot = require('dot-object');

var jsonObject = // as above ;-);

var convertJsonObjectToDot = dot.dot(jsonObject);

console.log(convertJsonObjectToDot);

输出如下所示:

{
  info.firstName : 'aamir',
  info.lastName : 'ryu',
  info.email : 'aamiryu@gmail.com
}

请耐心等待,这是我在stackoverflow上的第一个答案,因为我正在寻找相同的东西,我找到了一个解决方案,希望它可以帮助你。