项目中出现了这样一个问题,内嵌唯一索引不生效导致出现不合预期的数据。
找下原因。
document如下:
@Data
@Document(collection = "out")
@CompoundIndexes({
@CompoundIndex(name = "inner_unique", def = "{'inner.key':1}", unique = true)
})
public class OutDocument {
@Id
private String id;
private String code;
private String name;
private List<InnerDocument> inner;
}
@Data
@AllArgsConstructor
public class InnerDocument {
private String key;
private String value;
}
测试方法:
@Test
public void saveOrUpdate() {
OutDocument outDocument = new OutDocument();
outDocument.setCode("QWER001");
outDocument.setName("测试索引");
List<InnerDocument> innerDocuments = Arrays.asList(new InnerDocument("001", "潘森"), new InnerDocument("002", "妖姬"));
outDocument.setInner(innerDocuments);
outDocumentRepository.save(outDocument).subscribe(System.out::println);
}
执行第一遍,看下数据:
{
"_id": ObjectId("5c2dc8c846ce5e00cc26239c"),
"code": "QWER001",
"name": "测试索引",
"inner": [
{
"key": "001",
"value": "潘森"
},
{
"key": "002",
"value": "妖姬"
}
],
"_class": "com.paranoia.webfluxreactive.collection.index.OutDocument"
}
再次执行这个插入方法:
Caused by: com.mongodb.MongoWriteException: E11000 duplicate key error collection: test.out index: inner_unique dup key: { : "001" }
索引生效。
到这里我们没有发现什么问题,姿势正确。
那么,换一个姿势,修改inner。
@Test
public void addToInnerIndex() {
Mono<OutDocument> documentMono = outDocumentRepository.findById("5c2dc8c846ce5e00cc26239c")
.map(result -> {
List<InnerDocument> inner = result.getInner();
inner.add(new InnerDocument("001", "潘森的爸爸"));
return result;
})
.flatMap(newOut -> outDocumentRepository.save(newOut));
documentMono.block();
}
看下数据:
{
"_id": ObjectId("5c2dc8c846ce5e00cc26239c"),
"code": "QWER001",
"name": "测试索引",
"inner": [
{
"key": "001",
"value": "潘森"
},
{
"key": "002",
"value": "妖姬"
},
{
"key": "001",
"value": "潘森的爸爸"
}
],
"_class": "com.paranoia.webfluxreactive.collection.index.OutDocument"
发现索引并没有生效,这说明这个姿势不对,不用jpa ,试一下template
@Test
public void addToInnerIndexTryTemplate() {
Query query = new Query(Criteria.where("code").is("QWER001"));
Update update = new Update();
update.addToSet("inner", new InnerDocument("001", "潘森的爷爷"));
reactiveMongoTemplate.updateMulti(query, update, OutDocument.class).block();
}
看下数据,
{
"_id": ObjectId("5c2dc8c846ce5e00cc26239c"),
"code": "QWER001",
"name": "测试索引",
"inner": [
{
"key": "001",
"value": "潘森"
},
{
"key": "002",
"value": "妖姬"
},
{
"key": "001",
"value": "潘森的爸爸"
},
{
"key": "001",
"value": "潘森的爷爷"
}
],
"_class": "com.paranoia.webfluxreactive.collection.index.OutDocument"
}
发现还是没有生效,看来这两种姿势都不会在修改内嵌数据的时候去适配索引。那么,这种情况到底该采用一个什么姿势?