我正在使用spring-data-elasticsearch和spring-data-jest将数据通过spring-boot应用程序存储在elasticsearch中。
当我运行spring-boot应用程序时,所有内容都存储在elasticsearch中,如果我通过owningFacilityId或projectId删除文档,则所有内容都会很好地同步,并且文档将被删除。
执行junit测试时会出现问题,该测试通过不删除数据通过拥有FacilityId / projectId功能来测试删除。
带注释的@Document的Elasticsearch Java映射类:
@Document(indexName = "search-object")
public class SearchObject implements Serializable {
@Id
private String id;
private Long entityId;
private SearchEntityType type;
private String name;
private Map<String, String> attributes = new HashMap<>();
private Long owningFacilityId;
private Long projectId;
// getter + setter
ElasticSearchRepository:
public interface SearchEntityRepository extends ElasticsearchRepository<SearchObject, String> {
SearchObject findFirstByEntityIdAndType(Long entityId, SearchEntityType type);
void deleteByOwningFacilityId(Long owningFacilityId);
void deleteByProjectId(Long projectId);
}
服务类实现
@Component
public class SearchEntityService {
private final Logger log = LoggerFactory.getLogger(SearchEntityService.class);
@Autowired
private SearchEntityRepository searchEntityRepository;
// ...
public void deleteByOwningFacilityId(Long id) {
log.debug("Start: delete by owning facility id {}", id);
if (id != null) {
searchEntityRepository.deleteByOwningFacilityId(id);
}
log.debug("End: delete by owning facility id {}", id);
}
}
测试用例失败:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LibalApp.class)
public class SearchEntityServiceTest {
@Autowired
private SearchEntityService searchEntityService;
// ...
@Test
@Transactional
public void deleteByOwningFacilityId() {
for (SearchEntityType type : SearchEntityType.values()) {
searchEntityService.save(new SearchObject()
.setProjectId(4l)
.setOwningFacilityId(5l)
.setEntityId(6l)
.setName("DEFAULT SEARCH OBJECT")
.setType(type)
.addAttribute("ATTRIBUTE_KEY", "ATTRIBUTE VALUE"));
}
final Page<SearchObject> searchObjectsByProject = searchEntityService.search(4l, "*", PageRequest.of(0, SearchEntityType.values().length - 1));
Assert.assertEquals(searchObjectsByProject.getTotalElements(), SearchEntityType.values().length);
searchEntityService.deleteByOwningFacilityId(5l);
final Page<SearchObject> searchObjectsByProjectAfterDeletion = searchEntityService.search(4l, "*", PageRequest.of(0, SearchEntityType.values().length - 1));
Assert.assertEquals(0, searchObjectsByProjectAfterDeletion.getTotalElements());
}
}
Junit-Runner输出(带有存储的文档)
---> SearchObject{id='ed18ec56-6087-4b59-a506-e6f784b3e872', entityId=6, type=FACILITY, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='d8b752aa-012d-4996-a676-7053d4539a5d', entityId=6, type=FLOOR, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='55b70315-0f6b-4cff-8de9-540e58f2af16', entityId=6, type=SPACE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='f8cc5f8b-a8e5-416e-a8d6-59237d6f7903', entityId=6, type=ASSET_COMPONENT, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='cf14acca-c2ee-4f40-9c6c-3f48609b88f4', entityId=6, type=TYPE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='e9633c4c-1c38-4ddc-83b1-ab1fb2ddf0f3', entityId=6, type=SYSTEM, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='6ccea72c-4504-4685-b45c-7c5d69576161', entityId=6, type=ZONE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='bc38c439-1dfd-44ae-85e8-744582f1b006', entityId=6, type=RESOURCE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='5fbd03d3-ee7d-4da4-9b21-6482b834a7ec', entityId=6, type=JOB, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='791b2191-95d8-44cf-9502-b474d652a224', entityId=6, type=SPARE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='552cac26-b4e3-4b77-a480-b4e845b57998', entityId=6, type=ISSUE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='fa7b3554-9e69-4e14-97fb-72aaf68251fd', entityId=6, type=IMPACT, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='c336b491-dd90-49ec-aaf8-eea7a1034a5a', entityId=6, type=DOCUMENT, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='13d5b32d-0ee9-4f30-b95c-3887bf773e72', entityId=6, type=ASSET_COMPONENT_ASSEMBLY, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='a19b1019-0a10-425a-bf0a-372b0f2f5b56', entityId=6, type=TYPE_ASSEMBLY, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='28d3fb54-e23f-44a3-9ba3-0d241840e052', entityId=6, type=CONNECTION, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='5ec26f46-7b43-4037-9559-ff735e42f249', entityId=6, type=COORDINATE, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
---> SearchObject{id='71ab1b1d-06d0-4c43-a866-df745a73a900', entityId=6, type=CONTACT, name='DEFAULT SEARCH OBJECT', attributes={ATTRIBUTE_KEY=ATTRIBUTE VALUE}, owningFacilityId=5, projectId=4}
java.lang.AssertionError:
Expected :0
Actual :18
<Click to see difference>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:631)
at de.libal.service.search.SearchEntityServiceTest.deleteByOwningFacilityId(SearchEntityServiceTest.java:239)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
依赖项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<!-- <version>2.0.5.RELEASE</version> -->
</dependency>
<!-- Spring Data Jest dependencies for Elasticsearch -->
<dependency>
<groupId>com.github.vanroy</groupId>
<artifactId>spring-boot-starter-data-jest</artifactId>
<!-- <version>3.1.5.RELEASE</version> -->
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j2-mock needed to create embedded elasticsearch instance with SLF4J -->
<dependency>
<groupId>de.dentrassi.elasticsearch</groupId>
<artifactId>log4j2-mock</artifactId>
<version>${log4j2-mock.version}</version>
<scope>runtime</scope>
</dependency>
从搜索方法中提取:
final QueryBuilder projectMatchQuery = matchQuery("projectId", projectId);
final BoolQueryBuilder searchTermShouldQuery = QueryBuilders.boolQuery()
.minimumShouldMatch(1)
.should(queryStringQuery(query));
final BoolQueryBuilder must = QueryBuilders.boolQuery()
.must(searchTermShouldQuery)
.must(projectMatchQuery);
return searchEntityRepository.search(must, pageable);
任何帮助或提示都会有所帮助。
我刚刚检查了执行deleteByOwningFacilityId()
时执行的Spring Data Elasticsearch 3.0(旧版本)的代码:
if(tree.isDelete()) {
Object result = countOrGetDocumentsForDelete(query, accessor);
elasticsearchOperations.delete(query, queryMethod.getEntityInformation().getJavaType());
return result;
}
测试中缺少的是索引的刷新,您可以将服务实现更改为:
@Component
public class SearchEntityService {
private final Logger log = LoggerFactory.getLogger(SearchEntityService.class);
@Autowired
private SearchEntityRepository searchEntityRepository;
public void deleteByOwningFacilityId(Long id) {
log.debug("Start: delete by owning facility id {}", id);
if (id != null) {
searchEntityRepository.deleteByOwningFacilityId(id);
searchEntityRepository.refresh(); // <----
}
log.debug("End: delete by owning facility id {}", id);
}
}
在即将发布的Spring Data Elasticsearch第4版中,所有修改文档的存储库方法都将自动执行此刷新。