一尘不染

Wilcard搜索或elasticsearch中的部分匹配

elasticsearch

我正在尝试为最终用户提供搜索类型,这更像sqlserver。我能够为给定的SQL场景实现ES查询:

 select * from table where name like '%pete%' and type != 'xyz and type!='abc'

但是ES查询不适用于此sql查询

  select * from table where name like '%peter tom%' and type != 'xyz and type!='abc'

在我的elasticsearch以及通配符查询中,我还需要执行一些布尔过滤查询

{
"query": {
"filtered": {
"filter": {
"bool": {
"should": [
{
"query": {
"wildcard": {
"name":
{ "value": "*pete*" }
}
}
}
],
"must_not": [
{
"match":
{ "type": "xyz" }
}, {
"match":
{ "type": "abc" }
}
]
}
}
}
}
}

上面的带有通配符搜索的弹性查询可以很好地工作,并让我获得所有与pete匹配且不是xyz和abc类型的文档。但是当我尝试使用以空格分隔的2个独立单词执行通配符时,相同的查询返回我为空,如图所示下面。例如

{
    "query": {
    "filtered": {
    "filter": {
    "bool": {
    "should": [
    {
    "query": {
    "wildcard": {
    "name":
    { "value": "*peter tom*" }
    }
    }
    }
    ],
    "must_not": [
    {
    "match":
    { "type": "xyz" }
    }, {
    "match":
    { "type": "abc" }
    }
    ]
    }
    }
    }
    }
    }

我的映射如下:

{
  "properties": {
     "name": {
      "type": "string"
    }
    "type": {
      "type": "string"
    }
  }
}

我应该使用什么查询才能对以空格分隔的单词进行通配符搜索


阅读 324

收藏
2020-06-22

共1个答案

一尘不染

最有效的解决方案涉及利用ngram标记器来标记name字段的某些部分。例如,如果您有一个名称,如petertomson,则ngram令牌生成器将对它进行令牌化和索引,如下所示:

  • pe
    pet
    pete
    peter
    peter t
    peter to
    peter tom
    peter toms
    peter tomso
    eter tomson
    ter tomson
    er tomson
    r tomson
    tomson
    tomson
    omson
    mson
    son
    on

因此,将其编入索引后,搜索这些标记中的任何一个都会peter thomson在其中检索您的文档。

让我们创建索引:

PUT likequery
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_ngram_analyzer": {
          "tokenizer": "my_ngram_tokenizer"
        }
      },
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "nGram",
          "min_gram": "2",
          "max_gram": "15"
        }
      }
    }
  },
  "mappings": {
    "typename": {
      "properties": {
        "name": {
          "type": "string",
          "fields": {
            "search": {
              "type": "string",
              "analyzer": "my_ngram_analyzer"
            }
          }
        },
        "type": {
          "type": "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}

然后,您将可以通过一个简单且非常有效的term查询进行如下搜索:

POST likequery/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name.search": "peter tom"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "type": "xyz"
          }
        },
        {
          "match": {
            "type": "abc"
          }
        }
      ]
    }
  }
}
2020-06-22