solr - SOLR中的全文基于特定字段的子字符串
问题描述
我在我正在从事的项目中使用 Apache Solr。我已经完成了所有设置,并且还能够执行 SOLR 查询。但是 - 我对 SOLR 的一种行为感到困惑 - 即使在论坛上搜索后 - 也无法理解这种行为。
在我的 solr 架构中,我有一个field
类型为solr.TextField
. 我正在尝试对其进行fullTextSearch。仅当我*
在搜索关键字前后都包含通配符时,查询才会返回结果。如果我只在最后包含它,它就不起作用(例如searchWord*
:)
*
但是,许多在线论坛在 solr/lucene 搜索词的开头提到不支持。
请在下面找到schema.xml
。注意:我使用的是 solr v 7.4.0
<?xml version="1.0" encoding="utf-8" ?>
<schema name="blog_schema" version="1.4">
<types>
<fieldType name="string" class="solr.StrField" />
<fieldType name="text" class="solr.TextField" />
<fieldType name="long" class="org.apache.solr.schema.LongPointField" docValues="true" />
<fieldType name="date" class="org.apache.solr.schema.DatePointField" docValues="true" sortMissingLast="true" omitNorms="true"/>
</types>
<fields>
<field name="post_id" type="string" indexed="true" stored="true" required="true" />
<field name="title" type="string" indexed="true" stored="true" required="true" />
<field name="author" type="string" indexed="true" stored="true" required="true" />
<field name="corpus" type="text" indexed="true" stored="true" required="false" />
<field name="fullText" type="text" indexed="true" multiValued="true" />
<copyField source="*" dest="fullText" />
</fields>
<uniqueKey>post_id</uniqueKey>
</schema>
您可以看到我已将corpus
和fullText
字段定义为具有 type solr.TextField
。这两个字段都有大量的文本数据。
corpus
我打算对orfullText
字段进行全文搜索。为此,我使用 SOLR 查询如下:
corpus:*Thermodynamics*
上面的查询使用通配符,它确实有效并返回了我预期的结果。但我不明白这是否是正确的做法。许多论坛提到*
不支持搜索查询的开头。另一个观察结果是:如果我只使用语料库中的第一个单词并使用它进行搜索corpus: Thermodynamics*
- 它确实有效。然而,这不适用于随后出现在语料库中的单词(即所有不是语料库中第一个单词的单词)
我的印象是 SOLR 会理解空白/换行符将被忽略。所以 - 假设语料库有文本:Physics has a specialization for Thermodynamics and Heat
. 然后 SOLR 查询corpus: Thermodynamics*
orcorpus: Thermodynamics
应该可以工作,因为Thermodynamics
它本身就是一个词,并且 SOLR 会理解忽略应该忽略的空白。相反,我需要*
在搜索词的开头和结尾都包含通配符。
请帮我解释
1. 尽管论坛声称*
SOLR 不支持搜索词的开头,但为什么会出现这种行为。
2.我在corpus
字段上做全文的方式是否正确?
谢谢, 切坦
解决方案
这里有很多东西在起作用,所以让我们从字段类型开始:
<fieldType name="text" class="solr.TextField" />
.. 这并没有真正定义有用的字段类型。为此,您需要附加一个标记器和几个过滤器。标记器将文本拆分为标记,标记是产生匹配的东西。这称为分析链。
<fieldType name="text" class="solr.TextField">
<analyzer>
<tokenizer class="solr.WhitespaceTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
空白标记器会将“foo bar baz”拆分为三个标记foo
,bar
和baz
。任何查询都将执行相同的操作,并为令牌匹配令牌。这就是为什么你会得到一个匹配,即使搜索bar baz foo
和之前的顺序不同。您通常还希望至少附加 a LowercaseFilter
,以便获得不区分大小写的搜索 - 以及任何更多过滤器,具体取决于您的字段和域的用例。创建多个字段以执行不同的匹配,并分别权衡它们以获得对您的用户最有意义的文档评分。
如果没有这个分析链,我相信你实际上会得到与字符串字段相同的行为。
然后是通配符 - 如果存在通配符,则跳过整个分析链。这意味着在文本中搜索时使用通配符通常是一个坏主意。除非您尝试匹配单个标记(因为存在通配符时将跳过标记器),否则它不会做您认为的事情。所以你必须小心翼翼地做这件事,你可能会更频繁地陷入“为什么会发生这种情况”。
另一种方法是使用 NGramFilter ,它将单词中的每组字母(foo
变成f
、、、、fo
和foo
)拆分为单独的标记。您通常只想在索引时执行此操作,因此为您的字段使用单独的分析链(您通过配置中的参数定义 - 如果未给出类型,则将使用相同的链进行索引和查询。o
oo
o
type
建议不要使用前缀通配符 ( ) 的原因是,与检查后缀通配符 ( )*foo
相比,检查前缀通配符的成本更高。foo*
在后缀的情况下,您可以迭代索引 fromfoo
并继续前进,直到遇到不以 开头的内容foo
,而*foo
您必须有效地查看索引中的所有术语,因为没有排序顺序可以跟踪这些反过来。
输入反向通配符过滤器- 此过滤器的作用是,除了您的常规标记外,它还索引反向标记(或只是反向标记)。然后在查询时调用过滤器,并反转查询令牌 - 有效地索引oof
,然后在oof*
内部查询。这样,您就可以加快为该字段保持索引排序的速度,并且您不必查看每个标记。
此过滤器反转标记以提供更快的前导通配符和前缀查询。没有通配符的标记不会被反转。
推荐阅读
- r - 在ggplot散点图中以特定方式覆盖点
- cmd - 新的 CMD 窗口打印:“■@”未被识别为内部或外部命令
- javascript - 带有 Graph API 的 Outlook Web 插件 - 将当前项目作为 Outlook 项目附件发送时不显示内联图像
- sed - 如何使用 sed 删除第一个数字之前的所有字母?
- java - 如何使用 Apache poi 3.6 和 Apache Poi-ooxml-3.15 jar 读取 pptx 文件的内容?
- node.js - mongodb,添加聚合还是带一个字段
- webpack - Slim 4 & Webpack 错误清单文件不存在
- c++ - 使用 PANGO_ALIGN_MIDDLE 时 PangoCairo 文本截断
- ubuntu - 范围小时的 Cron 作业 ubuntu
- oracle - Oracle SUM(TO_NUMBER(REGEXP_SUBSTR WITH DECIMAL NUMBER