Spring boot mongodb:使用 updateMulti 更新具有自定义值的多条记录

问题描述 投票:0回答:2

我有一份记录清单。每条记录需要有 2 个字段:temp(摄氏温度)和 temp_F(华氏温度)。 temp 字段在大多数记录中都可用。但大多数记录中都缺少 temp_F。我想使用记录的临时值填充记录中缺少的 temp_F 值。这就是我正在做的事情:


Query updateTempFQuery = Query.query(Criteria.where("temp_F").isNull());
        List<TelemetryReport>reports = mongoTemplate.find(updateTempFQuery,TelemetryReport.class);

        for(TelemetryReport report:reports){
            if(report.getTemp() == null) continue;
            Double fahrenHeitValue = new BigDecimal("32").add(new BigDecimal("1.8").multiply(new BigDecimal(report.getTemp().toString()))).doubleValue();
           // temperature in fahrenheit = 32 + 1.8*(temp in celcius)
            Update applyUpdate = new Update().set("temp_F",fahrenHeitValue);
            mongoTemplate.updateFirst(updateTempFQuery,applyUpdate,TelemetryReport.class);
        }

但是由于记录数量巨大,代码会抛出超时错误。我想使用 updateMulti 和聚合或其他一些类似的方法来做到这一点。但我无法找到解决方案。请帮忙。

spring-boot spring-data-mongodb spring-mongodb
2个回答
0
投票

要优化更新 MongoDB 中大量记录的操作,可以使用

updateMulti
方法结合聚合管道。这种方法将使您能够以更有效的方式执行更新,特别是在处理大量记录时。

以下是如何修改代码以使用

updateMulti
:

  1. 构建查询:您已经有了查询来查找
    temp_F
    null
    的记录。
  2. 使用聚合管道创建更新:在 MongoDB 4.2 及更高版本中,您可以使用聚合管道进行更新操作,这允许您直接在更新命令中计算和设置
    temp_F
    的新值。

这是示例代码片段:

import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

// Your existing query to find records with null temp_F
Query updateTempFQuery = Query.query(Criteria.where("temp_F").isNull());

// Create an update using an aggregation pipeline
Update update = new Update().set("temp_F", 
    Arrays.asList(
        // Check if temp is not null
        new Document("$cond", Arrays.asList(
            new Document("$ne", Arrays.asList("$temp", null)),
            // Calculate Fahrenheit if temp is not null
            new Document("$add", Arrays.asList(32, new Document("$multiply", Arrays.asList(1.8, "$temp")))),
            // Keep the original temp_F if temp is null
            "$temp_F"
        ))
    )
);

// Use updateMulti to update all matching documents
mongoTemplate.updateMulti(updateTempFQuery, update, TelemetryReport.class);

在此代码中:

  • update
    是使用聚合管道创建的。
    $cond
    运算符用于检查
    temp
    是否不为空。如果
    temp
    不为空,则计算华氏度值。否则,它会保留原来的
    temp_F
  • updateMulti
    方法用于将此更新应用于与查询匹配的所有文档。

这种方法应该比迭代每个文档并逐个更新它们要快得多,特别是对于大型数据集。


0
投票

您可以使用简单的

updateMany
命令轻松完成此操作。

db.collection.updateMany(
   { "temp_F": { "$exists": false } },
   [
      {
         "$set": {
            "temp_F": {
               "$add": [
                  { "$multiply": [ 1.8, "$temp" ] },
                  32
               ]
            }
         }
      }
   ]
)

使用 Java API,MongoDB 命令将转换为以下代码:

Bson filter = Filters.eq("temp_F", null);
Bson update = Updates.combine(
    Updates.set("temp_F", 
        new Document("$add", Arrays.asList(
            new Document("$multiply", Arrays.asList(1.8, "$temp")),
            32
        ))
    )
);
UpdateResult result = collection.updateMany(filter, update);
© www.soinside.com 2019 - 2024. All rights reserved.