我正在为基本的CRUD操作以及灵活的搜索功能开发一个spring应用程序。我正在使用弹性搜索作为后端数据存储。
以下是我正在处理的JSON文档:-
{
"event-id":"7700908",
"date":"date:time",
"expiry": "some date",
"created-by":"",
"type":"x1|business|x3",
...
"dress-code": {
"mime-type": "image|audio|video|text",
"placeholder-type": "key|index",
"en_us": "Dress code guidelines...",
"en_in": "",
"placeholders": [
{
"key": "foo-bar",
"type": "snippet|image|quote",
"content": {
"mime-type": "image|audio|video|text",
"en_us": "some instruction placeholder",
"en_in": "some instruction placeholder",
"fr_FR": ""
}
}
]
},
"events": {
"event-id": "4534534",
"event-instruction": {
"mime-type": "audio|video|text",
"placeholder-type": "key|index",
"en_us": "The actual instruction, with/without placeholder (like put of 3d glasses etc...)",
"en_in": "",
"placeholders": [
{
"key": "foobar",
"type": "snippet|image|quote",
"content": {
"mime-type": "image|audio|video|text",
"en_us": "some instruction placeholder",
"en_in": "some instruction placeholder",
"fr_FR": ""
}
}
]
},
"rules":""
...
},
"refs": [
{
"person-id":"445245524",
...
}
]
}
然后下面的数据模型将在服务器上表示json以上:-
public class Event {
@JsonProperty("event-id")
private String eventId;
@JsonProperty("date")
private String date;
@JsonProperty("expiry")
private String expiry;
@JsonProperty("created-by")
private String createdBy;
@JsonProperty("type")
private String type;
...
@JsonProperty("dress-code")
private DressCode dressCode;
...
}
像往常一样,有 Controller 和 Repository 类。控制器类定义了从url到服务器方法的映射,而存储库类实现了所有必要的数据库操作。
插入和获取记录是非常基本的。但是,我在基于用户提供的标准编写搜索功能时遇到了一些问题。以下是我的初始方法:-
public List<Map<String, Object>> getAllEventsForCriteria(final Event event)
{
List<Map<String, Object>> resultAsList = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(INDEX);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(buildQuery(event));
searchRequest.source(searchSourceBuilder);
try {
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHit[] searchHits = searchResponse.getHits().getHits();
for (SearchHit hit : searchHits) {
resultAsList.add(hit.getSourceAsMap());
}
} catch (java.io.IOException e) {
e.getLocalizedMessage();
}
return resultAsList;
}
private QueryBuilder buildQuery(final Event event) {
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
if (event.getEventId() != null) {
QueryBuilder idTerm = QueryBuilders.termQuery("id", event.getQuizId());
queryBuilder.must(idTerm);
}
if (event.getDate() != null) {
QueryBuilder dateTerm = QueryBuilders.matchQuery("date", event.getDate());
queryBuilder.must(dateTerm);
}
if (event.getExpiry() != null) {
QueryBuilder expiryTerm = QueryBuilders.matchQuery("expiry", event.getExpiry());
queryBuilder.must(expiryTerm);
}
if (event.getCreatedBy() != null) {
QueryBuilder createdByTerm = QueryBuilders.matchQuery("created-by", event.getCreatedBy());
queryBuilder.must(createdByTerm);
}
if (event.getType() != null) {
QueryBuilder typeTerm = QueryBuilders.matchQuery("type", event.getType());
queryBuilder.must(typeTerm);
}
if (event.getDressCode() != null) {
if (event.getDressCode().getMimeType() != null) {
QueryBuilder mimeTerm = QueryBuilders.termQuery("dressCode.mime-type", event.getDressCode().getMimeType());
queryBuilder.must(mimeTerm);
}
if (event.getDressCode().getEnUs() != null) {
QueryBuilder enUSTerm = QueryBuilders.matchQuery("dressCode.en_us", event.getDressCode().getEnUs());
queryBuilder.must(enUSTerm);
}
if (event.getInstructions().getEnIn() != null) {
QueryBuilder enInTerm = QueryBuilders.matchQuery("dressCode.en_in", event.getDressCode().getEnIn());
queryBuilder.must(enInTerm);
}
}
return queryBuilder;
}
此方法面临两个主要问题:-
用户可以根据参数的任意组合进行搜索。这种方法更一般吗?
对于某些字段,我需要使搜索返回准确的结果。 matchQuery
将返回所有结果,而termQuery
将查询分为令牌。有/没有对JSON进行任何更改的出路是什么。