Я занимаюсь разработкой весеннего приложения для базовых операций CRUD, а также гибких функций поиска.Я использую эластичный поиск в качестве внутреннего хранилища данных.
Ниже приведен документ 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 определяет отображение из URL в метод сервера, тогда как класс Respository реализует все необходимые операции с базой данных.
Вставка и выборка записей довольно просты.Тем не менее, я столкнулся с несколькими проблемами при написании функциональности для поиска на основе критериев, предоставленных пользователем.Ниже мой первоначальный подход: -
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.