1

我对此进行了很多搜索并尝试了多种组合。但在所有尝试中都失败了:(。

这是我的问题:我在弹性搜索中创建了一个 jdbc-river,如下所示:

{
    "type" : "jdbc",
    "jdbc" : {
        "driver" : "oracle.jdbc.driver.OracleDriver",
        "url" : "jdbc:oracle:thin:@//ip:1521/db",
        "user" : "user",
        "password" : "pwd",
        "sql" : "select f1, f2, f3 from table"
    },
    "index" : {
        "index" : "subject2",
        "type" : "name2",
        "settings": {
            "analysis": {
                "analyzer": {
                    "my_analizer": {
                        "type": "custom",
                        "tokenizer": "my_pattern_tokenizer",
                        "filter": []
                    }
                },
                "tokenizer": {
                    "my_pattern_tokenizer": {
                        "type": "pattern",
                        "pattern": "$^"
                    }
                },
                "filter": []
            }
        }
    },
    "mappings": 
    {
        "subject2": 
        {
            "properties" : {
                "f1" : {"index" : "not_analyzed", "store": "yes", "analyzer": "my_analizer", "search_analyzer": "keyword", "type": "string"},
                "f2" : {"index" : "not_analyzed", "store": "yes", "analyzer": "my_analizer", "search_analyzer": "keyword", "type": "string"},
                "f3" : {"index" : "not_analyzed", "store": "yes", "analyzer": "my_analizer", "search_analyzer": "keyword", "type": "string"}
            }
        }
    }
}

我想实现一个自动完成功能,将用户输入的值与“f1”字段中的数据相匹配,但从一开始就是这样。

f1 字段中的数据就像

  • “哈丁县ABC”
  • “XYZ国”
  • “布拉布拉郡”
  • “布拉第二县”

根据要求,当用户键入“Coun”时,弹性搜索应该返回第二、第三和第四个结果,而不是第一个。我读到了“关键字”分析器,它使完整的单词成为标记,但我不知道在这种情况下不工作。

此外,如果用户键入“B 县”,则弹性搜索应返回第 3 和第 4 个选项。

以下是我查询结果的格式。选项1

{"from":0,"size":10, "query":{ "field" : { "f1" : "count*" } } }

选项 2

{"from":0,"size":10, "query":{ "span_first" : {
        "match" : {
            "span_term" : { "COMPANY" : "hardin" }
        },
        "end" : 1
    } } }

请告诉我我在这里做错了什么?提前致谢。

4

3 回答 3

1

在我回答之前,我想指出您正在定义一个分析器,然后设置index: not_analyzed这意味着不使用分析器。(如果您使用not_analyzed它与使用关键字分析器相同,则整个字符串,未触及,是一个标记。)

也是andanalyzer: my_analizer快捷方式,所以你的映射对我来说有点混乱......index_analyzer: my_analizersearch_analyzer: my_analizer

此外,除非您将其关闭,否则字段将存储在 中,_source除非您关闭_source存储并需要在结果集中返回该字段,否则您不需要单独存储字段。

我可以想到两种方法:

1. 使用match_phrase_prefix查询 - 更简单,更慢

不要定义任何分析器,你不需要它们。

映射:

"subject2": {
    "properties" : {
        "f1" : { "type": "string" },
        "f2" : { "type": "string" },
        "f3" : { "type": "string" },
        }
    }
}

询问:

"match_phrase_prefix" : {
    "f1" : {
        "query" : "Count"
    }
}

2.使用edge_ngram令牌过滤器 - 更难更快

"settings": {
    "analysis": {
        "analyzer": {
            "edge_autocomplete": {
                "type": "custom",
                "tokenizer": "keyword",
                "filter": ["my_edge_ngram"]
            }
        },
        "filter" : {
            "my_edge_ngram" : {
               "type": "edgeNGram",
               "min_gram": 2,
               "max_gram": 15
            }
        }
    }
}

映射:

"subject2": {
    "properties" : {
        "f1" : { "type": "string", "index": "edge_autocomplete" },
        "f2" : { "type": "string", "index": "edge_autocomplete" },
        "f3" : { "type": "string", "index": "edge_autocomplete" },
        }
    }
}

询问:

"match" : {
    "f1" : "Count",
    "analyzer": "keyword"
}

祝你好运!

于 2013-08-15T11:00:48.463 回答
0

你试过ngram过滤器吗?它将标记字符长度为“n”的字符串。因此,您的映射可能如下所示:

  {
    "settings": {
        "analysis": {
            "analyzer": {
                "autocomplete": {
                    "type": "custom",
                    "tokenizer": "standard",
                    "filter": ["standard", "lowercase", "kstem", "ngram"]
                }
            },
            "filter" : {
                "ngram" : {
                   "type": "ngram",
                   "min_gram": 2,
                   "max_gram": 15
                }
            }
        }
    },
    "mappings": {
        "subject2": {
            "properties" : {
                 "f1" : {
                    "type": "multi_field",
                     "fields": {
                         "f1": {
                             "type": "string"
                         },
                         "autocomplete": {
                             "analyzer": "autocomplete", 
                             "type": "string"
                         },
...

这将返回第二个、第三个和第四个结果的 ngram“计数”,这应该会给你想要的结果。

请注意,不需要将“f1”设置为multi_field字段。但是,当您不需要“自动完成”分析器时,例如在搜索结果中返回“f1”时,使用“f1”子字段的成本会更低。如果您确实使用“multi_field”,则可以在“f1”处访问“f1”(不使用点符号),但要访问“自动完成”,您需要使用点符号 - 所以“f1.autocomplete”。

于 2013-08-14T18:46:14.517 回答
0

虽然,我们最终实施的解决方案是多种方法,但“ramseykhalaf”的回答仍然是最接近的匹配。给他+1。

当用户输入带有空格的单词时,我所做的会触发匹配前缀查询并获得最接近的匹配结果来显示。

{"from":0,"size":10, "query":{ "match" : { "f1" : {"query" : "MICROSOU", "type" : "phrase_prefix", "boost":2} } } }

只要用户在空格后点击任何字符,我就会将查询模式更改为使用正则表达式查询字段,并且字段匹配中的多个单词再次非常接近用户正在寻找的内容。

{"from":0,"size":10, "query":{ "query_string" : { "default_field":"f1","query" : "micro int*", "boost":2 } } }

通过这种方式,我们得到了最接近此要求的解决方案。我很乐意获得满足上述用例的更多优化解决方案。

再添加一件事 - 现在我创建的河流是简单的普通香草,字段为“not_analyzed”,分析器为“keyword”

于 2013-08-19T12:00:36.930 回答