使用 ElasticSearch 搜索全球位置名称的有效方法是什么?

2024-01-07

我有以下提供的位置信息地名网 http://www.geonames.org/解析成关系数据库。使用这些信息,我尝试构建一个 ElasticSearch 索引,其中包含人口稠密的地名(城市)名称、行政区划(州、省等)名称、国家/地区名称和国家/地区代码。我的目标是提供类似于 Google 地图的位置搜索:

我不需要很酷的粗体突出显示,但我确实需要搜索以类似的方式返回类似的结果。我尝试使用由整个位置名称组成的单个位置字段(例如“美国德克萨斯州朗德罗克”)创建映射,并且我还尝试使用由位置的每个部分组成的五个单独的字段。我尝试过关键字和前缀查询以及edgengram分析器;我一直未能找到正确的配置来使其正常工作。

我应该使用哪些类型的分析器(索引和搜索)来实现我的目标?这个搜索不必像谷歌那样完美,但我希望它至少是相似的。

我确实想支持部分名称匹配,这就是为什么我一直在摆弄edgengram。例如,搜索“round r”应匹配 Round Rock, TX, United States。另外,我希望填充的地名(城市)名称以确切的搜索词开头的结果的排名高于其他结果。例如,搜索“round ro”应先匹配 Round Rock, TX, United States,然后再匹配 Round, Some Province, RO(罗马尼亚)。我希望我已经说得足够清楚了。

这是我当前的索引配置(这是 C# 中的匿名类型,稍后序列化为 JSON 并传递给 ElasticSearch API):

settings = new
{
    index = new
    {
        number_of_shards = 1,
        number_of_replicas = 0,
        refresh_interval = -1,
        analysis = new
        {
            analyzer = new
            {
                edgengram_index_analyzer = new
                {
                    type = "custom",
                    tokenizer = "index_tokenizer",
                    filter = new[] { "lowercase", "asciifolding" },
                    char_filter = new[] { "no_commas_char_filter" },
                    stopwords = new object[0]
                },
                search_analyzer = new
                {
                    type = "custom",
                    tokenizer = "standard",
                    filter = new[] { "lowercase", "asciifolding" },
                    char_filter = new[] { "no_commas_char_filter" },
                    stopwords = new object[0]
                }
            },
            tokenizer = new
            {
                index_tokenizer = new
                {
                    type = "edgeNGram",
                    min_gram = 1,
                    max_gram = 100
                }
            },
            char_filter = new
            {
                no_commas_char_filter = new
                {
                    type = "mapping",
                    mappings = new[] { ",=>" }
                }
            }
        }
    }
},
mappings = new
{
    location = new
    {
        _all = new { enabled = false },
        properties = new
        {
            populatedPlace = new { index_analyzer = "edgengram_index_analyzer", type = "string" },
            administrativeDivision = new { index_analyzer = "edgengram_index_analyzer", type = "string" },
            administrativeDivisionAbbreviation = new { index_analyzer = "edgengram_index_analyzer", type = "string" },
            country = new { index_analyzer = "edgengram_index_analyzer", type = "string" },
            countryCode = new { index_analyzer = "edgengram_index_analyzer", type = "string" },
            population = new { type = "long" }
        }
    }
}

这可能就是您正在寻找的:

  "analysis": {
    "tokenizer": {
      "name_tokenizer": {
        "type": "edgeNGram",
        "max_gram": 100,
        "min_gram": 2,
        "side": "front"
      }
    },
    "analyzer": {
      "name_analyzer": {
        "tokenizer": "whitespace",
        "type": "custom",
        "filter": ["lowercase", "multi_words", "name_filter"]
      },
    },
    "filter": {
      "multi_words": {
        "type": "shingle",
        "min_shingle_size": 2,
        "max_shingle_size": 10
      },
      "name_filter": {
        "type": "edgeNGram",
        "max_gram": 100,
        "min_gram": 2,
        "side": "front"
      },          
    }
  }

我认为使用name_analyzer将复制您正在谈论的谷歌搜索。您可以稍微调整配置以满足您的需求。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ElasticSearch 搜索全球位置名称的有效方法是什么? 的相关文章

随机推荐