如何使用带有 arrayFilter 的筛选位置运算符应用更新



>我在Mongodb 3.6上运行,使用mongo驱动程序3.4.3和弹簧数据mongo 1.5.10。以下是我的文档结构

{
  "_id": 12345,
  "_class": "com.example.ProductRates",
  "rates": [
    {
      "productId": NumberInt(1234),
      "rate": 100.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201801)
    },
    {
      "productId": NumberInt(1234),
      "rate": 200.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201802)
    },
    {
      "productId": NumberInt(1234),
      "rate": 400.0,
      "rateCardId": NumberInt(2),
      "month": NumberInt(201803)
    },
    {
      "productId": NumberInt(1235),
      "rate": 500.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201801)
    },
    {
      "productId": NumberInt(1235),
      "rate": 234,
      "rateCardId": NumberInt(2),
      "month": NumberInt(201803)
    }
  ]
}

我正在尝试对数据进行批量更新,如下所示

db.rates.update(
  { "_id" : 1234 },
  { $set: { "rates.$[item].rate": 200  } },
  { multi: true, 
   arrayFilters: [ { "item.rateCardId": {$in: [ 1, 2]} } ]
  }
)

现在并尝试将此代码转换为 java。以下是我能够为批量更新案例实现的代码。正如预期的那样,由于使用了 $[],下面的查询正在更新所有文档。我试图弄清楚如何使用位置数组更新运算符(如 $[one](在此处应用数组过滤器。

WriteResult wr = getMongoTemplate().updateMulti(
            new Query(where("rates.rateCardId").is(1234)),
            new Update().set("rates.$[].rate", 200),
            ProductRates.class);

此外,我找不到足够的教程或文档来建议如何在 Java 中应用所有复杂的 mongo 查询。 请建议是否有任何我可以参考的好书或教程。

这应该是:

WriteResult wr = getMongoTemplate().updateMulti(
  new Query(where("rates.rateCardId").is(1234)),
  new Update().set("rates.$[item].rate", 200),
  new UpdateOptions()
    .arrayFilters(
      Arrays.asList( Filters.in("item.rateCardId",Arrays.asList(1,2)) )
    ), 
  ProductRates.class
);

您需要确保底层 Java 驱动程序是 3.6.x 或更高版本,以便具有arrayFilters(),甚至可能支持添加UpdateOptions()

我发现 Neil 的答案在解决这个问题时很有用,但我想提供一个与他的代码片段中的调用略有不同的调用。

getMongoTemplate().getCollection("ProductRates").updateMany(
    new Document().append("rates.rateCardId", 1234),
    new Document().append("$set", new Document().append("rates.$[item].rate", 200)),
    new UpdateOptions()
        .arrayFilters(
            Collections.singletonList( Filters.in("item.rateCardId",
                                                 Arrays.asList(1,2)) ))
);

最新更新