如何用Elasticsearch和Logstash生成前缀数组用于自动补全建议器?
当然可以搞定!你需要的是生成后缀词元数组——就是从完整短语开始,逐步去掉前面的词,保留后面所有词的组合,不管是用Logstash还是Elasticsearch都能实现,下面给你两种具体的方案:
方案一:用Logstash的Ruby Filter生成数组
Logstash的split过滤器只能按分隔符拆分成单个元素,没法生成你要的后缀组合,所以我们可以用ruby过滤器自定义逻辑。假设你的原始字段叫input_text,要生成的目标数组字段叫suggest_tokens,配置如下:
filter { ruby { code => ' # 获取原始字段内容 input_text = event.get("input_text") if input_text # 按任意数量空格拆分单词(处理多个连续空格的情况) words = input_text.split(/\s+/) tokens = [] # 循环生成所有后缀组合 (0...words.length).each do |i| tokens << words[i..-1].join(" ") end # 将生成的数组赋值给目标字段 event.set("suggest_tokens", tokens) end ' } }
这段代码会把hi how are you处理成["hi how are you", "how are you", "are you", "you"],完全符合你的需求。
方案二:用Elasticsearch Ingest Pipeline处理
如果不想在Logstash层处理,也可以直接在Elasticsearch侧用 ingest pipeline 完成这个逻辑,适合直接向ES写入数据的场景。
首先创建一个处理pipeline:
PUT _ingest/pipeline/generate-suggest-tokens { "description": "生成自动补全用的后缀词元数组", "processors": [ { "script": { "source": """ def inputText = ctx.input_text; if (inputText != null) { # 先去除首尾空格,再按任意数量空格拆分单词 def words = inputText.trim().split(/\s+/); def tokens = []; # 遍历生成所有后缀组合 for (int i = 0; i < words.length; i++) { tokens.add(String.join(' ', Arrays.copyOfRange(words, i, words.length))); } ctx.suggest_tokens = tokens; } """ } } ] }
之后写入数据时,指定这个pipeline即可:
PUT your_index/_doc/1?pipeline=generate-suggest-tokens { "input_text": "hi how are you" }
或者你也可以把这个pipeline设置为索引的默认pipeline,这样写入时就不用每次指定了。
最后一步:配置Completion字段映射
不管用哪种方式生成了suggest_tokens数组,都需要把这个字段映射成Elasticsearch的completion类型,才能用于自动补全查询:
PUT your_index/_mapping { "properties": { "suggest_tokens": { "type": "completion" } } }
内容的提问来源于stack exchange,提问作者Gibbs
相关产品推荐
相关产品推荐

