Spring Boot не может обновить коллекцию sharded в Azure Cosmos db (MongoDb) - PullRequest
2 голосов
/ 14 марта 2019

У меня есть коллекция documentDev, присутствующая в базе данных с ключом шардинга как dNumber. Образец документа:

{
"_id" : "12831221wadaee23",
"dNumber" : "115",
"processed": false
}

Если я попытаюсь обновить этот документ с помощью любого инструмента запросов, используя команду, подобную -

db.documentDev.update({
  "_id" : ObjectId("12831221wadaee23"),
  "dNumber":"115"
},{
    $set:{"processed": true}}, 
{ multi: false, upsert: false}
)}`

Правильно обновляет документ. Но если я использую команду mongorepository Spring boot, как DocumentRepo.save (Объект) это исключение

  • Причина: com.mongodb.MongoCommandException: команда завершилась с ошибкой 61: «запрос в команде должен быть нацелен на один ключ шарда» на сервере by3prdddc01-docdb-3.documents.azure.com:10255. Полный ответ: {"_t": "OKMongoResponse", "ok": 0, "code": 61, "errmsg": "запрос в команде должен быть направлен на один ключ шарда", "$ err": "запрос в команде должен быть нацелен на один ключ шарда "}

Это мой DocumentObject:

@Document(collection = "documentDev")
public class DocumentDev
{
@Id
private String id;
private String dNumber;
private String fileName;
private boolean processed;
}

Это мой класс репозитория -

@Repository
public interface DocumentRepo extends MongoRepository<DocumentDev, 
String> { }

и значение, которое я пытаюсь обновить

  • Значение: doc: { "_id": "12831221wadaee23", "dNumber": "115", "обработано": правда }

функция, которую я пытаюсь выполнить:

@Autowired
DocumentRepo docRepo;

docRepo.save(doc); // Fails to execute

Примечание. В поле dNumber включено шифрование. И я успешно могу обновить, используя собственные запросы на NoSQL Tool. Мне также удалось выполнить операцию сохранения репозитория в коллекции без осколков.

Обновление: я могу обновить документ, создав собственный запрос с помощью MongoTemplate - Мой запрос выглядит так -

public DocumentDev updateProcessedFlag(DocumentDev request) {
    Query query = new Query();
    query.addCriteria(Criteria.where("_id").is(request.getId()));
    query.addCriteria(Criteria.where("dNumber").is(request.getDNumber()));
    Update update = new Update();
    update.set("processed", request.isProcessed());
    mongoTemplate.updateFirst(query, update, request.getClass());
    return request;
}

Но это не общее решение, так как в любом другом поле может быть обновление, а в моем документе могут быть и другие поля.

1 Ответ

0 голосов
/ 24 июля 2019

У меня была такая же проблема, решенная с помощью следующего хака:

@Configuration
public class ReactiveMongoConfig {

@Bean
public ReactiveMongoTemplate reactiveMongoTemplate(ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
                                                   MongoConverter converter,
                                                   MyService service) {
    return new ReactiveMongoTemplate(reactiveMongoDatabaseFactory, converter) {
        @Override
        protected Mono<UpdateResult> doUpdate(String collectionName, Query query, UpdateDefinition update, Class<?> entityClass, boolean upsert, boolean multi) {
            query.addCriteria(new Criteria("shardKey").is(service.getShardKey()));
            return super.doUpdate(collectionName, query, update, entityClass, upsert, multi);
        }
    };
}

}

Было бы неплохо иметь аннотацию @ShardKey, чтобы пометить поле документа как шард и добавить его взапрос автоматически.

...