更改文档结构后更新 mongoDB java 驱动程序中已有的文档

Updating pre-existing documents in mongoDB java driver when you've changed document structure

我有一个播放器数据数据库,其中包含该程序以前版本中的一些预先存在的字段。过时文档示例:

{
   "playername": "foo"
}

但是在新版本下生成的播放器文档是这样的:

{
   "playername": "bar",
   "playercurrency": 20
}

问题是,如果我尝试在 foo 上查询 playercurrency,我会得到 NullPointerException,因为 playercurrency 对于 foo 不存在。我想将 playercurrency 字段添加到 foo,而不影响可以存储在 foo 中的任何其他数据。我已经使用 $exists 示例尝试了一些代码:

players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playername", "")));
players.updateOne(new Document("playername", "foo"), new Document("$exists", new Document("playercurrency", 20)));

我的想法是它只更新 playercurrency 因为它不存在并且它会单独留下 playername 因为它存在。我可能使用的 exists 非常错误,如果是这样请告诉我,因为这是我的第一个 MongoDB 项目,我想尽可能多地学习。

您必须使用 java 执行此操作吗?每当我添加一个我想要的新字段时,我只需使用命令行来迁移所有现有文档。这将遍历所有没有玩家货币的玩家并将其设置为 0(更改为您想要的任何默认值):

db.players.find({playercurrency:null}).forEach(function(player) { player.playercurrency = 0; // or whatever default value db.players.save(player); });

这将导致您拥有以下文件:

{ "playername" : "foo", "playercurrency" : 0 }

{ "playername" : "bar", "playercurrency" : 20 }

所以我知道通常不赞成回答您自己的问题,但没有人真正发布我最终所做的事情我想借此机会感谢 @Mark Watson 的回答并最终指导我找到我的答案。

由于检查某个字段是否 null 在 MongoDB Java 驱动程序中不起作用,我需要找到一种不同的方法来了解什么时候准备更新.因此,经过一些研究后,我偶然发现了 this question,它帮助我想出了这段代码:

private static void updateValue(final String name, final Object defaultValue, final UUID key) {
        if (!exists(name, key)) {
            FindIterable iterable = players.find(new Document("_id", key));

            iterable.forEach(new Block<Document>() {

                @Override
                public void apply(Document document) {
                    players.updateOne(new Document("_id", key), new Document("$set", new Document(name, defaultValue)));
                }
            });
        }
    }

    private static boolean exists(String name, UUID key) {
        Document query = new Document(name, new Document("$exists", true)).append("_id", key);

        return players.count(query) == 1;
    }

显然,这对我想做的事情有点专门化,但只要稍加修改,就可以轻松更改它以处理您可能需要的任何内容。确保将 players 替换为您的 Collection 对象。