Spring Data Elasticsearch 通配符搜索

2024-03-19

我正在尝试寻找这个词blue在下面的文本列表中

“蓝宝石”、“蓝”、“蓝色”、“蓝色”、“蓝色”、 “蓝色”、“蓝黑”、“蓝”、“宝石蓝”、 “黑”、“绿”、“蓝”、“宝石蓝”

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
                  .withQuery(matchQuery("colorDescriptionCode", "blue")
                  .fuzziness(Fuzziness.ONE)
                  )
                  .build();

这工作正常,搜索结果返回以下记录以及分数

alue    2.8718023
Bluo    1.7804208
Bluo    1.7804208
BLUE    1.2270637
blue    1.2270637
Blue    1.2270637
Blue Black    1.1082436
Saphire Blue    0.7669148

但我无法使通配符发挥作用。 “SaphireBlue”和“BlueSaphire”也有望成为结果的一部分

我尝试了以下设置,但它不起作用。

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices("color")
                      .withQuery(matchQuery("colorDescriptionCode", "(.*?)blue")
                      .fuzziness(Fuzziness.ONE)
                      )
                      .build();

在堆栈溢出中,我观察到指定分析通配符的解决方案。

QueryBuilder queryBuilder = boolQuery().should(
                queryString("blue").analyzeWildcard(true)
                        .field("colorDescriptionCode", 2.0f);

我没有找到 queryString 静态方法。我正在使用 spring-data-elasticsearch 2.0.0.RELEASE 。

让我知道如何指定通配符,以便包含的所有单词blue也会在搜索结果中返回


我知道工作示例总是比理论更好,但我还是想先讲一点理论。 Elasticsearch 的核心是 Lucene。因此,在将文档写入 Lucene 索引之前,他会经历分析阶段。分析阶段可分为3个部分:

  1. 字符过滤;
  2. 标记化;
  3. 令牌过滤

在第一阶段,我们可以丢弃不需要的字符,例如 HTML 标签。有关字符过滤器的更多信息,您可以找到官方网站 https://www.elastic.co/guide/en/elasticsearch/reference/2.4/analysis-charfilters.html。 下一阶段要有趣得多。在这里,我们将输入文本拆分为标记,稍后将用于搜索。几个非常有用的分词器 https://www.elastic.co/guide/en/elasticsearch/reference/2.4/analysis-tokenizers.html:

  • 标准分词器。默认情况下使用它。分词器实现 Unicode 文本分段算法。在实践中,您可以使用它将文本拆分为单词并将这些单词用作标记。
  • n-gram 分词器。如果您想按单词的一部分进行搜索,这就是您所需要的。此分词器将文本拆分为 n 个项目的连续序列。例如,文本“for example”将被分割成这个标记序列"fo", "or", "r ", " e", "ex", "for", "or ex"n-gram 的长度是可变的,可以通过 min_gram 和 max_gram 参数进行配置。
  • 边缘 n-gram 分词器。与 n-gram 分词器的工作方式相同,除了一件事 - 此分词器不会增加偏移量。例如,文本“for example”将被分割成这个标记序列"fo", "for", "for ", "for e", "for ex", "for exa"ETC。 您可以在官方网站上找到有关分词器的更多信息。不幸的是,由于声誉较低,我无法发布更多链接。

下一阶段也非常有趣。将文本拆分为标记后,我们可以用它做很多有趣的事情。我再次给出一些非常有用的令牌过滤器示例:

  • 小写过滤器。在大多数情况下,我们希望获得不区分大小写的搜索,因此最好将标记变为小写。
  • 词干过滤器。当我们处理自然语言时,我们会遇到很多问题。问题之一是一个词可以有多种形式。词干过滤器帮助我们获取单词的词根形式。
  • 模糊过滤器。另一个问题是用户经常犯错。此过滤器添加包含可能的拼写错误的标记。

如果您有兴趣查看分析结果,可以使用这个术语“向量端点”

curl [ELASTIC_URL]:9200/[INDEX_NAME]/[TYPE_NAME]/[DOCUMENT_ID]/_termvectors?pretty

现在谈谈查询。查询分为 2 大组。这些组有 2 个显着差异:

  1. 请求是否会经过分析阶段;
  2. 该请求是否需要确切的答案(是或否)

示例包括匹配查询和术语查询。第一个将通过分析阶段,第二个则不会。第一个不会给我们具体的答案(但会给我们一个分数),第二个会给出。为文档创建映射时,我们可以为每个字段分别指定分析器和搜索分析器的索引。

现在关于 spring data elasticsearch 的信息。这里讲一下具体的例子是有道理的。假设我们有一个带有标题字段的文档,并且我们想要搜索有关该字段的信息。首先,创建一个包含 Elasticsearch 设置的文件。

{
 "analysis": {
    "analyzer": {
        "ngram_analyzer": {
            "tokenizer": "ngram_tokenizer",
            "filter": [
                "lowercase"
            ]
        },
        "edge_ngram_analyzer": {
            "tokenizer": "edge_ngram_tokenizer",
            "filter": [
                "lowercase"
            ]
        },
        "english_analyzer": {
            "tokenizer": "standard",
            "filter": [
                "lowercase",
                "english_stop",
                "unique",
                "english_possessive_stemmer",
                "english_stemmer"
            ]
        "keyword_analyzer": {
            "tokenizer": "keyword",
            "filter": ["lowercase"]
        }

   },
   "tokenizer": {
       "ngram_tokenizer": {
           "type": "ngram",
           "min_gram": 2,
           "max_gram": 20
       },
       "edge_ngram_tokenizer": {
           "type": "edge_ngram",
           "min_gram": 2,
           "max_gram": 20
       }
   },
   "filter": {
       "english_stop": {
           "type": "stop",
           "stopwords": "_english_"
       },
   "english_stemmer": {
       "type": "stemmer",
       "language": "english"
   },
   "english_possessive_stemmer": {
       "type": "stemmer",
       "language": "possessive_english"
   }
 }    
}

您可以将此设置保存到资源文件夹中。现在让我们看看我们的文档类

@Document(indexName = "document", type = "document")
@Setting(settingPath = "document_index_setting.json")
public class Document {

    @Id
    private String id;

    @MultiField(
        mainField = @Field(type = FieldType.String, 
                           index = not_analyzed),
        otherFields = {
                @InnerField(suffix = "edge_ngram",
                        type = FieldType.String,
                        indexAnalyzer = "edge_ngram_analyzer",
                        searchAnalyzer = "keyword_analyzer"),
                @InnerField(suffix = "ngram",
                        type = FieldType.String,
                        indexAnalyzer = "ngram_analyzer"),
                        searchAnalyzer = "keyword_analyzer"),
                @InnerField(suffix = "english",
                        type = FieldType.String,
                        indexAnalyzer = "english_analyzer")
        }
    )
    private String title;

    // getters and setters omitted

}

所以这里的字段标题包含三个内部字段:

  • title.edge_ngram用于使用关键字搜索分析器按边缘 n 元语法进行搜索。我们需要这个,因为我们不需要将查询拆分为边缘 n 元;
  • title.ngram用于通过 n-gram 进行搜索;
  • title.english用于以自然语言的细微差别进行搜索 以及主场标题。我们不分析这个,因为有时我们想按这个字段排序。 让我们使用简单的多重匹配查询来搜索所有这些字段:
String searchQuery = "blablabla";
MultiMatchQueryBuilder queryBuilder = multiMatchQuery(searchQuery)
    .field("title.edge_ngram", 2)
    .field("title.ngram")
    .field("title.english");
NativeSearchQueryBuilder searchBuilder = new NativeSearchQueryBuilder()
    .withIndices("document")
    .withTypes("document")
    .withQuery(queryBuilder)
    .withPageable(new PageRequest(page, pageSize));
elasticsearchTemplate.queryForPage(searchBuilder.build, 
                                   Document.class, 
                                   new SearchResultMapper() {
                                   //realisation omitted });

搜索是一个非常有趣且内容丰富的话题。我试图尽可能简短地回答,因此可能会出现令人困惑的时刻 - 请毫不犹豫地询问。

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

Spring Data Elasticsearch 通配符搜索 的相关文章

随机推荐

  • 下拉菜单中的 jvectormaps,NS_ERROR_FAILURE:

    我的 jvector 地图位于下拉菜单中 它在 safari opera 和 chrome 中运行良好 但会损坏 没有地图 和错误消息 NS ERROR FAILURE 2 0 2 min js 第 700 行 return this no
  • LinkedList不能序列化?

    这是我的课程 http pastebin com 3dc5Vb1t http pastebin com 3dc5Vb1t 当我尝试跑步时 BookStore b new BookStore b LoadFromXML Server MapP
  • 如何替换 Tkinter 应用程序中的图标?

    我在 Windows 10 上使用 Python 3 5 0 并且想要替换它 要更改图标 您应该使用iconbitmap or wm iconbitmap我的印象是您想要将其更改为的文件必须是 ico 文件 import tkinter a
  • C#:GPS跟踪系统[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 如何在 C net 中构建带有移动设备 带 GPS 的 GPS 跟踪系统 场景是 通过支持 GPS 的手机跟踪用户 服务工程师 这里没
  • 保持鼠兔 BlockingConnection 存活而不禁用心跳

    我正在使用 pika 0 10 0 和 python 2 7 版本开发 RabbitMQ 消费者 在我的消费者客户端中 我有一个根据输入消息运行一段时间的进程 时间可能从 3 到 40 分钟不等 我不想禁用心跳 相反 我正在寻找一些回滚机制
  • Ruby on Rails - 简单表单自动完成关联搜索

    我在基本任务管理应用程序中有一个表单 允许将任务分配给用户 任务属于用户 我为此使用简单表格 目前 该关联以典型方式填充 带有用户下拉列表 如下所示 但是 随着用户数量的增长 我希望将其更改为自动完成表单字段以查找用户 我尝试过遵循Rail
  • 使用原生SQL查询时如何指定数据类型?

    我正在使用休眠 我已经编写了本机 SQL 查询 我想指定其中一列的数据类型 如下所示 sqlQuery addScalar NAME STRING 我正在查询 5 列并且ID是其中的一栏 但如果我使用addScalar 它不返回所有列 只返
  • 用于 BLE 的 BluezV5.42 DBUS C API?

    我开发了 BLE 应用程序openwrt using BLUEZV5 30 我能够通过提取源代码来创建应用程序gatttool and hcitool 我还添加了这些工具提供的更多功能 例如阅读rssi 不过 我已经升级了我的bluez堆叠
  • JSON.net - 字段可以是 string 或 List

    我有一种情况JSON从一个返回REST service 返回电影对象列表 所有对象都包含大量信息 其中有几个字段REST 服务结果根据可用信息而变化 举个例子 电影总是有一些屏幕截图 图像 演员和导演 根据所讨论的电影 可能有一张或多张图像
  • Intersection Observer rootMargin 在 x 轴上未按预期工作

    我正在尝试使用交集观察器 API 为一个侧面项目实现图像延迟加载 我面临的问题是 无论我如何调整 x 轴的 rootMargin 例如 0px 300px 0px 0px 交叉点似乎只发生在视口上 预期 在进入视口之前相交 300px 时加
  • 是否可以在 C# 类库中创建 Windows 窗体?

    我一直在用 C 构建 DLL 类库 用作提供自定义 API 的应用程序的附加组件 到目前为止 它们主要包括与数据库 计算 磁盘操作等的接口 我很想知道是否可以在 DLL 类库内构建和显示 Windows 窗体 显示文本框 按钮等 I tri
  • 如果“cargo build”比直接运行 rustc 慢,为什么我应该使用 Cargo?

    我创建了一个简单的 hello world 程序 fn main println Hello world 编译代码时使用rustc vs cargo build 货物命令显得较慢 它需要1 6s for cargo build vs 1s
  • 我们如何在Python中通用地使用sin、cos、tan(包括用户定义的类型)?

    编辑 让我尝试改写并改进我的问题 旧版本附在底部 我正在寻找一种以类型通用的方式表达和使用自由函数的方法 例子 abs x maps to x abs next x maps to x next at least in Python 3 x
  • 如何使用nosetests测试函数是否在函数内被调用

    我正在尝试为项目设置一些自动单元测试 我有一些函数 作为副作用 它们偶尔会调用另一个函数 我想编写一个单元测试来测试第二个函数是否被调用 但我被难住了 下面是伪代码示例 def a self data self get if len dat
  • FIREBASE 警告:无效的查询字符串段:[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我在 Firebase 日志控制台中不断收到这些警告 FIREBASE 警告 无效的查询字符串段 我检查了所有内容 但找不到一些原
  • Reactjs 意外的标记“<”

    我用react redux redux创建了reactjs应用程序 启动reactjs项目时 在索引文件的第13行出现意外的令牌错误 索引文件如下 ERROR in src index js Module build failed Synt
  • VHDL 中的进程是可重入的吗?

    一个进程是否可以连续运行两次或多次VHDL 如果在进程的顺序执行未完成的情况下发生另一个事件 在敏感信号列表上 会发生什么 有可能还是我的VHDL流程中的模型完全错误 进程运行时不会发生任何事件 当进程被事件唤醒时 它会运行到完成 结束进程
  • 如何通过 C# 代码以编程方式构建解决方案文件?

    我有一个包含许多项目的大型解决方案 其中一个是安装项目 还有许多当前版本存储在单独的分支中 我有一个曾经在 NET 2 中工作的构建工具 但自从我们升级到 NET 4 后就不再工作了 在内部 新的 NET 4 版本的构建工具使用Micros
  • 如何估计 Spark DataFrame 中每列的大小(以字节为单位)?

    我有一个非常大的 Spark DataFrame 其中有许多列 我想对是否将它们保留在我的管道中做出明智的判断 部分取决于它们有多大 我所说的 有多大 是指缓存此 DataFrame 时 RAM 中的大小 以字节为单位 我希望这是对处理此数
  • Spring Data Elasticsearch 通配符搜索

    我正在尝试寻找这个词blue在下面的文本列表中 蓝宝石 蓝 蓝色 蓝色 蓝色 蓝色 蓝黑 蓝 宝石蓝 黑 绿 蓝 宝石蓝 SearchQuery searchQuery new NativeSearchQueryBuilder withIn