除了一组已知的字段外,如何取消设置所有字段?

Don*_*uts 12 mongodb mongodb-query

假设我的mongo集合中有一个文档,如下所示:

{
    "_id": 123,
    "field_to_prune": 
    {
        "keep_field_1": "some value",
        "random_field_1": "some value",
        "keep_field_2": "some value",
        "random_field_2": "some value",
        "random_field_3": "some value"
    }
}
Run Code Online (Sandbox Code Playgroud)

我想修剪该文档看起来像这样:

{
    "_id": 123,
    "field_to_prune": 
    {
        "keep_field_1": "some value",
        "keep_field_2": "some value"
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我的问题是我不知道"随机"字段名称是什么.在mongo中,除了几个已知的字段之外,我将如何取消所有字段?

我可以想到几种方法,但我不知道语法..我可以选择所有字段NAMES,然后为每一个取消设置该字段.有点像这样:

[Some query to find all field names under "field_to_prune" for id 123].forEach(function(i) { 
    var key = "field_to_prune." + i;
    print("removing field: " + key);
    var mod = {"$unset": {}};
    mod["$unset"][key] = "";

    db.myCollection.update({ _id: "123" }, mod);
});
Run Code Online (Sandbox Code Playgroud)

我想要做的另一种方法是取消设置字段名称不在我定义的字符串数组中的位置.不知道怎么做.有任何想法吗?

Leo*_*tny 2

如果您不关心原子性,那么您可以这样做save

doc = db.myCollection.findOne({"_id": 123});
for (k in doc.field_to_prune) {
  if (k === 'keep_field_1') continue;
  if (k === 'keep_field_2') continue;
  delete doc.field_to_prune[k];
}
db.myCollection.save(doc);
Run Code Online (Sandbox Code Playgroud)

该解决方案的主要问题是它不是原子的。因此,在和doc之间的任何更新都将丢失。findOnesave

另一种方法是实际上unset所有不需要的字段而不是保存doc

doc = db.myCollection.findOne({"_id": 123});
unset = {};
for (k in doc.field_to_prune) {
  if (k === 'keep_field_1') continue;
  if (k === 'keep_field_2') continue;
  unset['field_to_prune.'+k] = 1;
}
db.myCollection.update({_id: doc._id}, {$unset: unset});
Run Code Online (Sandbox Code Playgroud)

这个解决方案要好得多,因为 mongoupdate以原子方式运行,因此不会丢失任何更新。而且您不需要另一个集合来完成您想要的操作。