Spring Boot无法更新Azure Cosmos db(MongoDb)上的分片集合

nis*_*hta 6 java sharding mongodb spring-boot

我在数据库中存在一个集合“ documentDev”,其中的分片键为“ dNumber”示例文档:

{
"_id" : "12831221wadaee23",
"dNumber" : "115",
"processed": false
}
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用以下命令通过任何查询工具来更新此文档:

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

它将正确更新文档。但是如果我确实使用Spring Boot的mongorepository命令(例如DocumentRepo.save(Object)),则会引发异常

  • 引起原因:com.mongodb.MongoCommandException:命令失败,错误61:服务器上的查询“命令查询必须以单个分片键为目标” by3prdddc01-docdb-3.documents.azure.com:10255。完整的响应为{“ _t”:“ OKMongoResponse”,“ ok”:0,“代码”:61,“ errmsg”:“命令中的查询必须以单个分片键为目标”,“ $ err”:“命令中的查询必须以单个分片键为目标。“}

这是我的DocumentObject:

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

这是我的存储库类-

@Repository
public interface DocumentRepo extends MongoRepository<DocumentDev, 
String> { }
Run Code Online (Sandbox Code Playgroud)

和价值,我试图更新

  • 值:doc:{“ _ id”:“ 12831221wadaee23”,“ dNumber”:“ 115”,“已处理”:true}

我正在尝试执行的功能:

@Autowired
DocumentRepo docRepo;

docRepo.save(doc); // Fails to execute
Run Code Online (Sandbox Code Playgroud)

注意:我在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;
}
Run Code Online (Sandbox Code Playgroud)

但这不是通用解决方案,因为其他任何字段都可能有更新,而我的文档也可能还有其他字段。

prz*_*zem 1

我遇到了同样的问题,通过以下 hack 解决了:

@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);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有一个注释 @ShardKey 将文档字段标记为分片并将其添加到自动查询中,那就太好了。