【问题标题】:How to add new field to all documents in a collection trough Mongock?如何通过 Mongock 向集合中的所有文档添加新字段?
【发布时间】:2021-05-27 01:07:01
【问题描述】:

我有一个文档集合,如下所示:

[
    {
        "firstName" : "Foo",
        "phone" : "+1 111 1111",
        "car": "Toyota"
    },
    {
        "firstName" : "Bar",
        "phone" : "+2 222 2222",
        "car": "Honda"
    }
]

我想为这个集合“Persons”中的每个文档添加一个新字段,我可以在控制台上执行语法,但是由于我需要以某种方式存储更改,所以我们使用的是 Mongock。而且我找不到执行updateMongockTemplate 的方法。 文件的{ "key" : "value" } 是静态的,我什至不需要变量来传递它们,最终的文件应该是这样的:

[
    {
        "firstName" : "Foo",
        "phone" : "+1 111 1111",
        "car": "Toyota",
        "species" : "human"
    },
    {
        "firstName" : "Bar",
        "phone" : "+2 222 2222",
        "car": "Honda",
        "species" : "human"
    }
]

我不知道如何在MongockTemplate 内部执行如下查询:

db.getCollection('Persons').update(
  {},
  { $set: {"species": "human"} },
  false,
  true
)

Here's the StackTrace:

```java
22:18:48.237 [main] ERROR io.changock.runner.core.ChangockBase - Error in changock process. ABORTED MIGRATION
io.changock.migration.api.exception.ChangockException: Error in method[UpdateAddTypeField.updateAddTypeField] : 'com.mongodb.client.result.UpdateResult org.springframework.data.mongodb.core.MongoTemplate.updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)'
    at io.changock.runner.core.MigrationExecutor.processExceptionOnChangeSetExecution(MigrationExecutor.java:195)
    at io.changock.runner.core.MigrationExecutor.processSingleChangeSet(MigrationExecutor.java:102)
    at io.changock.runner.core.MigrationExecutor.lambda$processSingleChangeLog$2(MigrationExecutor.java:94)
    at io.changock.runner.core.MigrationExecutor.executeInTransactionIfStrategyOrUsualIfNot(MigrationExecutor.java:80)
    at io.changock.runner.core.MigrationExecutor.processSingleChangeLog(MigrationExecutor.java:94)
    at io.changock.runner.core.MigrationExecutor.lambda$processAllChangeLogs$1(MigrationExecutor.java:88)
    at io.changock.runner.core.MigrationExecutor.executeInTransactionIfStrategyOrUsualIfNot(MigrationExecutor.java:80)
    at io.changock.runner.core.MigrationExecutor.processAllChangeLogs(MigrationExecutor.java:88)
    at io.changock.runner.core.MigrationExecutor.lambda$executeMigration$0(MigrationExecutor.java:69)
    at io.changock.runner.core.MigrationExecutor.executeInTransactionIfStrategyOrUsualIfNot(MigrationExecutor.java:80)
    at io.changock.runner.core.MigrationExecutor.executeMigration(MigrationExecutor.java:69)
    at io.changock.runner.spring.v5.core.SpringMigrationExecutor.executeMigration(SpringMigrationExecutor.java:38)
    at io.changock.runner.core.ChangockBase.execute(ChangockBase.java:44)
    at io.changock.runner.spring.v5.ChangockSpringBuilderBase$ChangockSpringApplicationRunner.run(ChangockSpringBuilderBase.java:110)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
    at com.hiden.subhiden.project.subhidenprojecterviceApplication.main(subhidenprojecterviceApplication.java:22)
Caused by: java.lang.reflect.InvocationTargetException: null
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at io.changock.runner.core.MigrationExecutor.executeChangeSetMethod(MigrationExecutor.java:174)
    at io.changock.runner.core.MigrationExecutor.executeAndLogChangeSet(MigrationExecutor.java:127)
    at io.changock.runner.spring.v5.core.SpringMigrationExecutor.executeAndLogChangeSet(SpringMigrationExecutor.java:44)
    at io.changock.runner.core.MigrationExecutor.processSingleChangeSet(MigrationExecutor.java:100)
    ... 16 common frames omitted
Caused by: java.lang.NoSuchMethodError: 'com.mongodb.client.result.UpdateResult org.springframework.data.mongodb.core.MongoTemplate.updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)'
    at com.github.cloudyrock.mongock.driver.mongodb.springdata.v2.decorator.impl.MongockTemplate.lambda$updateMulti$53(MongockTemplate.java:383)
    at io.changock.driver.api.lock.guard.invoker.LockGuardInvokerImpl.invoke(LockGuardInvokerImpl.java:18)
    at com.github.cloudyrock.mongock.driver.mongodb.springdata.v2.decorator.impl.MongockTemplate.updateMulti(MongockTemplate.java:383)
    at com.hiden.subhiden.project.dbchangelogs.UpdateAddTypeField.updateAddTypeField(UpdateAddTypeField.java:32)
    ... 24 common frames omitted
22:18:48.315 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter - 

***************************
APPLICATION FAILED TO START
***************************

Description:

An attempt was made to call a method that does not exist. The attempt was made from the following location:

    com.github.cloudyrock.mongock.driver.mongodb.springdata.v2.decorator.impl.MongockTemplate.lambda$updateMulti$53(MongockTemplate.java:383)

The following method did not exist:

    'com.mongodb.client.result.UpdateResult org.springframework.data.mongodb.core.MongoTemplate.updateMulti(org.springframework.data.mongodb.core.query.Query, org.springframework.data.mongodb.core.query.Update, java.lang.String)'

The method's class, org.springframework.data.mongodb.core.MongoTemplate, is available from the following locations:

    jar:file:/home/johnnes/.m2/repository/org/springframework/data/spring-data-mongodb/3.0.5.RELEASE/spring-data-mongodb-3.0.5.RELEASE.jar!/org/springframework/data/mongodb/core/MongoTemplate.class

The class hierarchy was loaded from the following locations:

    org.springframework.data.mongodb.core.MongoTemplate: file:/home/johnnes/.m2/repository/org/springframework/data/spring-data-mongodb/3.0.5.RELEASE/spring-data-mongodb-3.0.5.RELEASE.jar


Action:

Correct the classpath of your application so that it contains a single, compatible version of org.springframework.data.mongodb.core.MongoTemplate


Process finished with exit code 1

【问题讨论】:

    标签: java spring-boot mongotemplate mongock


    【解决方案1】:

    虽然之前的答案仍然有效,但在您发布错误日志后,我想我找到了问题所在。您正在使用不兼容的 MongoDB Spring Data 和 Mongock Driver 版本。一方面,您使用的是 MongoDB Spring Data 3.0.5.RELEASE,另一方面,您使用的是 Mongock 驱动程序 mongodb-spring-data-v2,该驱动程序旨在与 Spring Data 2 一起使用。您应该改用 mongodb-spring-data-v3

    欲了解更多信息,请查看official documentation

    【讨论】:

      【解决方案2】:

      所以,经过多次尝试,我找到了以下解决方案: 通过 MongockTemplate 获取 MongoTemplate Impl 的实例并使用它来代替 MongockTemplate。我仍然不知道它为什么起作用。如果我弄明白了,我会更新这个帖子。

      @ChangeSet(order = "1", id = "updateData", author = "J. Souza")
        public void updateCollectionAddSpecieField(MongockTemplate mongockTemplate) {
      
          MongoTemplate template = mongockTemplate.getImpl();
      
          Query query = new Query();
          query.addCriteria(where(SPECIES_FIELD).exists(false));
          Update update = new Update();
          update.set(SPECIES, HUMAN);
          UpdateResult updateResult = template
              .updateMulti(query, update, "Collection-Name");
      
          log.info("Matched {} | Modified {}",
              updateResult.getMatchedCount(), updateResult.getModifiedCount());
        }
      

      【讨论】:

      • 您好 Johnnes,虽然这似乎是一个临时解决方案,但您不应该直接使用 mongockTemplate.getImpl(),您的更改在 Mongock 锁下并没有真正同步。可能有效,因为您的更改花费的时间少于锁定的初始时间。但是,如果出于任何原因,您的更改花费了更长的时间,它可能会产生意想不到的结果。请问您能否提供使用 MongockTemplate 时的错误日志,以便我帮助您找出问题所在?
      • @Mongockteam 我已经更新了错误日志,我想我忘了在这里提到你。
      • 感谢错误日志。我们发布了一个我们认为是解决方案的新答案。
      【解决方案3】:

      你可以用普通的 MongoTemplate 做任何事情,你也可以用 MongockTemplate 做。

      在这种情况下,您可以调整 UpdateOptions 和其他一些东西,但它可以很简单

             Document updater = new Document()
                .append("$set", new Document().append("species", "human"));
              
             mongockTemplate.getCollection("Persons")
                 .updateMany(new Document(), updater);
      

      【讨论】:

      • 是的,我尝试了你提到的方法,但 Mongock 一直出错。我不知道为什么,因为我还有一个脚本可以为我的一些收藏添加新索引,它仍然可以正常工作!
      • 我们已经用 Mongock 进行了尝试,效果很好。假设 Mongock 配置正确,我能想到的唯一可能性是您在 Mongock 中使用启用事务。这种操作和交易存在一些已知问题
      猜你喜欢
      • 2021-06-04
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多