Java 带约束的Spring Boot弹性搜索查询
我对这个弹性搜索和spring boot的世界还很陌生,在过去的2-3天里我一直在尝试搜索这个解决方案,可惜我没能找到(可能是因为我是新手) 我在弹性搜索中有3列,第一列是Id,第二列是name(我正在创建自动完成API),第三列是数字字段。我的用例是,对于第3列中的特定数字,我希望第2列中的自动完成建议 这是我用这段代码实现的,它可以工作:Java 带约束的Spring Boot弹性搜索查询,java,spring,spring-boot,elasticsearch,full-text-search,Java,Spring,Spring Boot,elasticsearch,Full Text Search,我对这个弹性搜索和spring boot的世界还很陌生,在过去的2-3天里我一直在尝试搜索这个解决方案,可惜我没能找到(可能是因为我是新手) 我在弹性搜索中有3列,第一列是Id,第二列是name(我正在创建自动完成API),第三列是数字字段。我的用例是,对于第3列中的特定数字,我希望第2列中的自动完成建议 这是我用这段代码实现的,它可以工作:repo.findByNumbersAndName(String,String) 但这不允许我设置模糊性、通配符查询和其他搜索参数,所以我尝试使用Query
repo.findByNumbersAndName(String,String)
但这不允许我设置模糊性、通配符查询和其他搜索参数,所以我尝试使用QueryBuilder,但我在构建逻辑方面没有成功(我基本上尝试使用BooleanQueryBuilder),所以如果有人能在这方面帮助我,那将非常有帮助
Spring启动版本-2.4.2
提前谢谢
编辑1:-
为了更好地理解我的用例,假设这是我在弹性搜索中存储的内容
Id | Name | Numbers |
-----------------------
a1 | ashwin | 1 |
a2 | Ram | 3 |
a3 | Kumar | 2 |
a4 | Some | 2 |
a5 | body | 1 |
a6 | any | 3 |
a7 | one | 4 |
a8 | ashwin | 2 |
现在我应该可以控制指定我的查询,对于这个数字(比如说1),如果输入自动完成“a”,那么自动完成的可能性是多少。然后程序应该只搜索数字列中有数字“1”的可能性,因此在这个场景中只有一个输出是“ashwin”
编辑2:-
我相信我的配置和查询方法与您所做的相同,我将只粘贴我所做的。一个更新是,尽管数据库中的Number字段包含整数,但它们存储为String数据类型,但这会对term查询产生任何影响吗
这是我的elastic-analyzer.json
{
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 3,
"max_gram": 30
}
},
"analyzer": {
"autocomplete_search": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"stop"
]
},
"autocomplete_index": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter",
"stop"
]
}
}
}
}
我正在使用它生成一个查询:-
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("Number", number))
.must(QueryBuilders.matchQuery("Name", search_word));
上面以这种格式生成查询-
{
"bool" : {
"must" : [
{
"term" : {
"Number" : {
"value" : "1",
"boost" : 1.0
}
}
},
{
"match" : {
"Name" : {
"query" : "ash",
"operator" : "OR",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"boost" : 1.0
}
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
这是产生空数组,无法理解为什么?我觉得下面的属性相当于您在索引映射中提到的属性
@Id
@Field(type = FieldType.Text)
private String Id;
@Field(type = FieldType.Text, analyzer = "autocomplete_index", searchAnalyzer = "autocomplete_search")
private String Name;
@Field(type = FieldType.Text)
private String Number;
谢谢@ESCoder
编辑3:-
我也是在@ESCoder的帮助下偶然发现的
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("Number", search_number).boost(1f).operator(Operator.AND))
.must(QueryBuilders.matchQuery("Name", keyword).boost(0.4f));
这是为ElasticSearch生成的查询spring
{
"bool" : {
"must" : [
{
"match" : {
"Number" : {
"query" : "1",
"operator" : "AND",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"boost" : 1.0
}
}
},
{
"match" : {
"Name" : {
"query" : "ash",
"operator" : "OR",
"fuzziness" : "1",
"prefix_length" : 0,
"max_expansions" : 50,
"fuzzy_transpositions" : true,
"lenient" : false,
"zero_terms_query" : "NONE",
"auto_generate_synonyms_phrase_query" : true,
"boost" : 0.4
}
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
添加带有索引数据、映射、搜索查询和搜索结果的工作示例 索引映射:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
索引数据:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
搜索查询:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
搜索结果:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
更新1:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
使用当前索引映射设置,将为ashwin
GET /_analyze
{
"analyzer" : "autocomplete",
"text" : "ashwin"
}
代币包括:
{
"tokens": [
{
"token": "ash",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "ashw",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "ashwi",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "ashwin",
"start_offset": 0,
"end_offset": 6,
"type": "<ALPHANUM>",
"position": 0
}
]
}
{
“代币”:[
{
“记号”:“灰烬”,
“起始偏移量”:0,
“端部偏移”:6,
“类型”:“,
“位置”:0
},
{
“令牌”:“ashw”,
“起始偏移量”:0,
“端部偏移”:6,
“类型”:“,
“位置”:0
},
{
“令牌”:“阿什维”,
“起始偏移量”:0,
“端部偏移”:6,
“类型”:“,
“位置”:0
},
{
“令牌”:“ashwin”,
“起始偏移量”:0,
“端部偏移”:6,
“类型”:“,
“位置”:0
}
]
}
您需要修改索引映射,而不是“最小图”:3
您需要将其更改为“最小图”:1
更新2:
{
"settings": {
"analysis": {
"filter": {
"autocomplete_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 4
}
},
"analyzer": {
"autocomplete": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"autocomplete_filter"
]
}
}
}
},
"mappings": {
"properties": {
"Name": {
"type": "text",
"analyzer": "autocomplete",
"search_analyzer": "standard"
},
"Id": {
"type": "text"
},
"Numbers": {
"type": "integer"
}
}
}
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
{
"Name": "ashwin",
"Id": "a1",
"Numbers": 2
}
{
"query": {
"bool": {
"must": [
{
"match": {
"Name": "a"
}
},
{
"term": {
"Numbers": 1
}
}
]
}
}
}
"hits": [
{
"_index": "66923434",
"_type": "_doc",
"_id": "1",
"_score": 1.2630212,
"_source": {
"Name": "ashwin",
"Id": "a1",
"Numbers": 1
}
}
]
您甚至需要将
“search\u analyzer”
更改为standard
Hi@ESCoder,感谢您的快速回复!!我已经更新了我的答案,请务必让我知道我的代码中是否有任何错误,因为我没有发现我以前实现的与您现在发送的有任何区别。再次感谢@ashwinramkumar请查看答案的更新部分,并让我知道这是否解决了您的问题?如果我对搜索的查询是“ash”(3个字母的单词),其中数字=“1”,它应该能够在ngram=3(意味着“ash”作为标记存在)时提取它,但当我运行结果时,我仍然得到一个空列表。谢谢@ashwinramkumar您需要设置“搜索分析器”:“标准”
。请按照上面的答案进行索引映射。现在,当您搜索ash
时,您将得到所需的结果。让我知道这是否适合你:-)是的。。增加了投票权!!再次感谢你的帮助