Java 在文档MongoDB中添加或更改节点

Java 在文档MongoDB中添加或更改节点,java,mongodb,mongodb-query,Java,Mongodb,Mongodb Query,我有一个现有文档,可能有也可能没有这样的嵌入式节点“cls”: product { _id: .., product_id: "myuniqueid", name: "some name", cls: { some data } } 现在,我需要的是: 如果产品不存在,则什么也不会发生 如果产品存在且cls存在,则更新cls零件 如果产品存在而cls不存在,则将cls部件添加到该产品中 我发现如果我设置upsert=false,什么也不会发生。然而,我倾向于相信ups

我有一个现有文档,可能有也可能没有这样的嵌入式节点“cls”:

product { 
   _id: ..,
   product_id: "myuniqueid",
   name: "some name",
   cls: { some data }
}
现在,我需要的是:

  • 如果产品不存在,则什么也不会发生
  • 如果产品存在且cls存在,则更新cls零件
  • 如果产品存在而cls不存在,则将cls部件添加到该产品中
  • 我发现如果我设置
    upsert=false
    ,什么也不会发生。然而,我倾向于相信
    upsert
    适用于嵌入文档(产品),而不是嵌入文档(cls)

    所以基本上我写:

    public static UpdateResult upsert(MongoCollection<Document> coll, Bson filter, Document doc, boolean upsert) {
        BasicDBObject action = new BasicDBObject("$set", doc);
        UpdateOptions options = new UpdateOptions().upsert(upsert);
        return coll.updateOne(filter, action, options);
    }
    
    它似乎没有更新任何内容,至少在cls还不存在的情况下。因此,
    upsert
    选项几乎适用于cls节点,而不是嵌入产品。MongoDB文档对这一问题不是决定性的

    我可能会将
    upsert
    更改为true,并将product\u id作为唯一索引,以确保不会插入任何外来产品。但我真正想要的是一个解释

    除非你想在标准不匹配的情况下“创建”一些东西,否则你永远都不会想要。这是唯一的目的,因为您基本上是在说“这是一个‘独特’文档的组成部分,如果您没有找到,请为我创建一个”。这不是你的逻辑所暗示的。事实上,这要简单得多

    你真正想要的是:

  • 找到或不找到产品

  • 找到某个对象后,将此字段设置为该值

  • 基本上你自己的第二点和第三点就是上面的第二点。这里没有任何建议“在找不到的地方创建一个新文档”,这是“upsert”行为,因此您忽略了它

    所以本质上,只是:

    这真的再简单不过了,因为这些都是基本的力学原理


    您将看到的另一件非常好的事情是,如果您想要将“cls”设置为与已有的完全相同,那么实际上,
    $set
    操作实际上什么都不做,因为更新足够智能,可以意识到它是相同的,并且不会尝试更改数据。它仍然报告“匹配”,但幕后的最新统计数据表明,在这种情况下没有更新。

    好的!因此,我应该直接将新的BasicDBObject(“cls”,justClsValue)添加到操作中,而不是首先将其添加到嵌入产品中!谢谢很高兴今天我学到了一些东西。@dexter你问题中最大的含糊不清之处是“产品中的数据是什么?”,它只是作为一个神秘的变量出现,没有任何解释。
    $set
    (和其他更新操作符)的要点是,它允许您指定实际要用某些内容更新的“字段路径”,而不是仅仅覆盖整个文档。所以,如果您只想“在我找到产品的地方设置cls”,那么这就是您所要做的。另一个“巨大的歧义”是,“产品”是主文档还是文档中的一系列“嵌入项”?这是一个如何提问的技巧。
    product.append("cls", clsDoc);
    DBUtil.upsert(products, new BasicDBObject("product_id", pid), product, false);
    
    collection.updateOne(
        new BasicDBObject("product_id", pid),
        new BasicDBObject("$set",
            new BasicDBObject("cls", justClsValue)
        )
    );