有我的示例文档。
"id" : "1",
"title" : "test",
"description" : "test",
"price" : 100.0,
"category_id" : "1",
"characteristics" : [
{
"characteristic_id" : "1",
"text_value" : "red"
},
{
"characteristic_id" : "2",
"numeric_value" : 15
},
{
"characteristic_id" : "3",
"numeric_value" : 20
}
]
"id" : "2",
"title" : "test",
"description" : "test",
"price" : 200.0,
"category_id" : "1",
"characteristics" : [
{
"characteristic_id" : "1",
"text_value" : "blue"
},
{
"characteristic_id" : "2",
"numeric_value" : 10
},
{
"characteristic_id" : "3",
"numeric_value" : 5
}
]
对我的索引的查询必须是这样的。我如何使用 Elasticsearch 的新 Java Api 客户端来编写此内容?
GET product/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "characteristics",
"query": {
"bool": {
"must": [
{
"term": {
"characteristics.characteristic_id": 1
}
},
{
"term": {
"characteristics.text_value": "blue"
}
}
]
}
}
}
},
{
"nested": {
"path": "characteristics",
"query": {
"bool": {
"must": [
{
"term": {
"characteristics.characteristic_id": 3
}
},
{
"range": {
"characteristics.numeric_value": {
"gte": 1,
"lte": 7
}
}
}
]
}
}
}
},
{
"term": {
"category_id": 1
}
},
{
"range": {
"price": {
"gt": 10.0,
"lt": 500.0
}
}
}
],
"should": [
{
"match": {
"title": "te"
}
}
]
}
}
}
官方文档中的信息很少。如果没有正常的文档,我是否应该使用这个 API 并手动编写所有请求?
Java代码
List<Query> filters = new ArrayList<>();
if(requestPayload.getPriceTo() != 0) {
filters.add(RangeQuery.of(r -> r
.field("price")
.gte(JsonData.of(requestPayload.getPriceFrom()))
.lte(JsonData.of(requestPayload.getPriceTo())))
._toQuery());
}
if(requestPayload.getCategoryId() != null) {
filters.add(TermQuery.of(t -> t
.field("category_id")
.value(requestPayload.getCategoryId()))
._toQuery());
}
List<RangeQuery> rangeList = new ArrayList<>();
for(var category : requestPayload.getFilters().getNumericValues()) {
for (var numericValue : category.getValues()) {
if (numericValue.getFrom() != null && numericValue.getTo() != null) {
rangeList.add(RangeQuery.of(r -> r
.field("characteristics.numeric_value")
.gte(JsonData.of(numericValue.getFrom()))
.lte(JsonData.of(numericValue.getTo()))));
}
}
filters.add(NestedQuery.of(n -> n
.path("characteristics")
.query(q -> q
.bool(b -> {
b.must(m -> m
.term(t -> t
.field("characteristics.characteristic_id")
.value(category.getCharacteristicId())));
for (RangeQuery rangeQuery : rangeList)
b.should(s -> s.range(rangeQuery));
b.minimumShouldMatch("1");
return b;
})
))._toQuery());
}
for(var category : requestPayload.getFilters().getTextValues()) {
List<FieldValue> textValuesList = new ArrayList<>();
for(var textValue : category.getValues()) {
textValuesList.add(FieldValue.of(textValue));
}
TermsQueryField textValues = TermsQueryField.of(tf -> tf.value(textValuesList));
if(!textValuesList.isEmpty()) {
filters.add(NestedQuery.of(n -> n
.path("characteristics")
.query(q -> q
.bool(b -> b
.must(m -> m
.term(t -> t
.field("characteristics.characteristic_id")
.value(category.getCharacteristicId())))
.must(m -> m
.terms(t -> t
.field("characteristics.text_value")
.terms(textValues))))))
._toQuery());
}
}
BoolQuery boolQuery = BoolQuery.of(b -> b
.filter(filters)
.should(s -> s
.match(m -> m
.field("title")
.query(requestPayload.getText()))));
SearchResponse<ProductDocument> response = esClient.search(s -> s
.index("product")
.query(q -> q.bool(boolQuery)),
ProductDocument.class);
List<Hit<ProductDocument>> hits = response.hits().hits();
for (Hit<ProductDocument> hit: hits) {
System.out.println(hit.source());
}
Json查询
{
"query": {
"bool": {
"should": {
"match": { "title": { "query": "te" } }
},
"filter": [
{
"range": { "price": { "gte": 1.0, "lte": 100.0 } }
},
{
"term": { "category_id": "1" }
},
{
"nested": {
"path": "characteristics",
"query": {
"bool": {
"must": [
{ "term": { "characteristics.characteristic_id": "1" } },
{ "terms": { "characteristics.text_value": ["red", "blue"] } }
]
}
}
}
},
{
"nested": {
"path": "characteristics",
"query": {
"bool": {
"must": [
{ "term": { "characteristics.characteristic_id": "4" } },
{ "terms": { "characteristics.text_value": ["yes"] } }
]
}
}
}
},
{
"nested": {
"path": "characteristics",
"query": {
"bool": {
"must": [
{ "term": { "characteristics.characteristic_id": "2" } }
],
"should": [
{ "range": { "characteristics.numeric_value": { "gte": 1, "lte": 20 } } },
{ "range": { "characteristics.numeric_value": { "gte": 21, "lte": 30 } } }
],
"minimum_should_match": 1
}
}
}
}
]
}
}
}