elasticsearch,full-text-search,Java,Spring,Spring Boot,elasticsearch,Full Text Search" /> elasticsearch,full-text-search,Java,Spring,Spring Boot,elasticsearch,Full Text Search" />

Java 带约束的Spring Boot弹性搜索查询

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

我对这个弹性搜索和spring boot的世界还很陌生,在过去的2-3天里我一直在尝试搜索这个解决方案,可惜我没能找到(可能是因为我是新手)

我在弹性搜索中有3列,第一列是Id,第二列是name(我正在创建自动完成API),第三列是数字字段。我的用例是,对于第3列中的特定数字,我希望第2列中的自动完成建议

这是我用这段代码实现的,它可以工作:
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
时,您将得到所需的结果。让我知道这是否适合你:-)是的。。增加了投票权!!再次感谢你的帮助