【问题标题】:How to setup date and fuzzy title search on elasticsearch如何在 elasticsearch 上设置日期和模糊标题搜索
【发布时间】:2020-02-12 17:41:00
【问题描述】:

我正在构建一个带有 Angular 7 前端的 Rails 5 应用程序。 在这个应用程序中,我使用的是 Searchkick(一个 Elasticsearch gem),并且我已经索引了一个名为 Event 的模型,它具有属性 title(字符串)和 starts_at(日期时间)。

我希望能够在搜索控制器中构建一个查询,我可以在其中执行以下操作:

  1. 使用模糊搜索来搜索标题,这意味着它不必 100% 匹配(现在需要)。
  2. 在日期范围与 starts_at 匹配的情况下搜索索引事件。

这是我的控制器索引方法

def index
        args = {}
        args[:eventable_id] = params[:id]
        args[:eventable_type] = params[:type]
        args[:title] = params[:title] if params[:title].present?
        if params[:starts_at].present?
            args[:starts_at] = {}
            args[:starts_at][:gte] = params[:starts_at].to_date.beginning_of_day
            args[:starts_at][:lte] = params[:ends_at].to_date.end_of_day
        end
        @events = Event.search where: args, page: params[:page], per_page: params[:per_page]
    end

我已将此行添加到我的事件模型中

searchkick text_middle: [:title]

这是实际运行的查询

{
    "query": {
        "bool": {
            "must": {
                "match_all": {}
            },
            "filter": [{
                "term": {
                    "eventable_id": "2"
                }
            }, {
                "term": {
                    "eventable_type": "Space"
                }
            }, {
                "term": {
                    "title": "nice event"
                }
            }, {
                "range": {
                    "starts_at": {
                        "from": "2020-02-01T00:00:00.000Z",
                        "include_lower": true,
                        "to": "2020-02-29T23:59:59.999Z",
                        "include_upper": true
                    }
                }
            }]
        }
    },
    "timeout": "11s",
    "_source": false,
    "size": 10000
}

日期搜索不起作用(但我没有收到任何错误)并且标题搜索必须匹配 100%(即使是大小写)。

感谢大家的帮助!

【问题讨论】:

  • 我建议使用 ngram,而不是使用模糊搜索。模糊搜索的问题在于,无论您设置什么偏移量,它都会将您正确匹配的术语视为等于不正确匹配的术语。所以“abc”匹配“abc”和“aac”,偏移量为1。对于范围查询,您需要一个带有shouldmust子句的bool查询和您的实际范围字段查询{range: {year: {gte: params[:date], lte: params[:date], boost: 10}}} .我在 ES 7.3 中使用了类似的查询子句。
  • 嗯,我明白了。我如何将它与上面的哈希一起使用来构建查询?

标签: ruby-on-rails elasticsearch searchkick


【解决方案1】:

我建议使用 ngram 分析器,而不是使用模糊查询。

这是一个 ngram 分析器的示例:

analyzer: {
    ngram_analyzer: {
        type: "custom",
        tokenizer: "standard",
        filter: ["lowercase", "ngram_filter"],
        char_filter: [
            "replace_dots"
        ]
    }
},
filter: {
    ngram_filter: {
        type: "ngram",
        min_gram: "3",
        max_gram: "20",
    }
}

您还必须将此代码添加到您的设置索引中:

 max_ngram_diff: 17

然后在您的映射中,确保您创建了两个字段。常规字段的 1 个映射,例如 name,然后是 ngram 字段的另一个映射,例如 name.ngram

在我的查询中,我喜欢将我的 name 字段提升 10 并将我的 name.ngram 字段提升 5,以便首先呈现精确匹配。不过,您将不得不玩这个。

关于您的范围查询,我使用的是gtelte。这是一个例子:

query:{
   bool: {
      must: {
          range: {date: {gte: params[:date], lte: params[:date], boost: 10}}
      }
   }
}

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多