- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们有一个符合 OData 的 API,可以将部分全文搜索需求委托(delegate)给 Elasticsearch 集群。
由于 OData 表达式可能变得非常复杂,因此我们决定将它们简单地转换为等效的 Lucene 查询语法,并将其提供给 query_string
查询。
我们确实支持一些与文本相关的 OData 过滤器表达式,例如:
startswith(field,'bla')
endswith(field,'bla')
substringof('bla',field)
name eq 'bla'
analyzed
、
not_analyzed
或两者(即通过多字段)。
table
)、仅其一部分(例如
tab
)或多个标记(例如
table 1.
、
table 10
等)。
startswith(name,'table 1')
必须 “1 12上层表” endswith(name,'table 1')
必须匹配 “房间1,表1 ”, “子表1 ”, “表1 ”, “杰夫表1 ” substringof('table 1',name)
必须匹配 “大表1 背”, “表1 ”, “表1 ”, “小表1 2” name eq 'table 1'
必须匹配“ 表 1 ”、“ 表 1 ”、“0x1049 407919 405619 405617startswith
/endswith
的第二个参数的内容,分别是 substringof
的第一个参数,分别是 eq
的右侧值,并尝试是否完全匹配) token 完全匹配或仅部分匹配。query_string
中,我们使用 Regular Expression syntax 匹配 not_analyzed
字段。由于该字段是 not_analyzed
并且搜索必须不区分大小写,我们在准备正则表达式以提供给查询的同时进行自己的标记化,以便提出类似的内容,即这等效于 OData 过滤器 endswith(name,'table 8')
(= > 匹配所有 name
以“table 8”结尾的文档) "query": {
"query_string": {
"query": "name.raw:/.*(T|t)(A|a)(B|b)(L|l)(E|e) 8/",
"lowercase_expanded_terms": false,
"analyze_wildcard": true
}
}
substringof('table 1',name)
来匹配它,所以“table”是一个完全匹配的标记,而“1”只是下一个标记的前缀。eq
)和 startswith
完美工作。endswith
故障substringof('table 112', name)
会产生 107 个文档。搜索更具体的情况,例如 endswith(name, 'table 112')
会产生 1525 个文档,而它应该会产生较少的文档(后缀匹配应该是子字符串匹配的子集)。更深入地检查我发现了一些不匹配的内容,例如“Social Club, Table 12”(不包含“112”)或“Order 312”(既不包含“table”也不包含“112”)。我想这是因为它们以“12”结尾,这是标记“112”的有效克,因此匹配。substringof
故障substringof('table',name)
匹配“Party table”、“Alex on big table”但不匹配“Table 1”、“table 112”等。搜索 substringof('tabl',name)
不匹配任何内容query_string
查询,主要是因为 OData 表达式(无论它们可能多么复杂)将不断被翻译成它们的 Lucene 等价物。我知道我们正在用 Elasticsearch Query DSL 的强大功能与 Lucene 的查询语法进行权衡,Lucene 的查询语法有点不强大,表达能力也不强,但这是我们无法真正改变的。不过,我们非常接近!search_as_you_type
的新数据类型,它 native 允许这种行为。阅读更多信息:https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-as-you-type.html 最佳答案
这是一个有趣的用例。这是我的看法:
{
"settings": {
"analysis": {
"analyzer": {
"my_ngram_analyzer": {
"tokenizer": "my_ngram_tokenizer",
"filter": ["lowercase"]
},
"my_edge_ngram_analyzer": {
"tokenizer": "my_edge_ngram_tokenizer",
"filter": ["lowercase"]
},
"my_reverse_edge_ngram_analyzer": {
"tokenizer": "keyword",
"filter" : ["lowercase","reverse","substring","reverse"]
},
"lowercase_keyword": {
"type": "custom",
"filter": ["lowercase"],
"tokenizer": "keyword"
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": "2",
"max_gram": "25"
},
"my_edge_ngram_tokenizer": {
"type": "edgeNGram",
"min_gram": "2",
"max_gram": "25"
}
},
"filter": {
"substring": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 25
}
}
}
},
"mappings": {
"test_type": {
"properties": {
"text": {
"type": "string",
"analyzer": "my_ngram_analyzer",
"fields": {
"starts_with": {
"type": "string",
"analyzer": "my_edge_ngram_analyzer"
},
"ends_with": {
"type": "string",
"analyzer": "my_reverse_edge_ngram_analyzer"
},
"exact_case_insensitive_match": {
"type": "string",
"analyzer": "lowercase_keyword"
}
}
}
}
}
}
}
my_ngram_analyzer
用于将每个文本分成小块,这些块有多大取决于您的用例。出于测试目的,我选择了 25 个字符。 lowercase
因为您说不区分大小写而使用。基本上,这是用于 substringof('table 1',name)
的标记器.查询很简单:{
"query": {
"term": {
"text": {
"value": "table 1"
}
}
}
}
my_edge_ngram_analyzer
用于从头开始拆分文本,专门用于 startswith(name,'table 1')
用例。同样,查询很简单:{
"query": {
"term": {
"text.starts_with": {
"value": "table 1"
}
}
}
}
endswith(name,'table 1')
的部分.为此,我定义了 my_reverse_edge_ngram_analyzer
它使用 keyword
分词器和 lowercase
和一个 edgeNGram
过滤器前后是 reverse
filter .这个分词器的主要作用是在 edgeNGrams 中分割文本,但边缘是文本的结尾,而不是开头(就像常规的 edgeNGram
一样)。{
"query": {
"term": {
"text.ends_with": {
"value": "table 1"
}
}
}
}
name eq 'table 1'
案例,一个简单的keyword
分词器和 lowercase
过滤器应该这样做{
"query": {
"term": {
"text.exact_case_insensitive_match": {
"value": "table 1"
}
}
}
}
query_string
,这稍微改变了解决方案,因为我指望
term
不分析输入文本并将其与索引中的术语之一完全匹配。
query_string
“模拟”
if the appropriate analyzer
is specified for it .
{
"query": {
"query_string": {
"query": "text.starts_with:(\"table 1\")",
"analyzer": "lowercase_keyword"
}
}
}
关于regex - 如何明智地结合 shingles 和 edgeNgram 来提供灵活的全文搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30666371/
我正在尝试使用 Solr 在用户搜索 (例如,“blue skinny jeans”中的“skinny jeans”)中找到完全匹配的类别。我正在使用以下类型定义:
我有一个与 shingleAnalyzer 相关的问题,我想创建搜索词的 shingles,同时将它们提供给 lucene 进行搜索 String term = "new york"; String[
我有以下文件: 南非 北非 我想从以下位置检索我的“南非”文档: 非洲 (a) 南非 (b) 非洲 (c) 我定义了以下过滤器和分析器: POST test_index { "settings":
我目前正在使用 lucene 索引网页。目的是能够快速提取哪个页面包含某个表达式(通常是 1、2 或 3 个词),以及页面中还包含哪些其他词(或其中的 1 到 3 个词组)。这将用于构建/丰富/更改词
实现类似 Google 的自动完成的方法之一是在 Solr 1.4 中结合 shingles 和 termvector 组件。 首先,我们使用 shingles 组件生成所有 n-gram 分布,然后
我正在使用 SOLR 5.2 构建应用程序,我需要这种类型的匹配: 如果我存储了字段名称:“bla1 bla2”和名称:“bla2 some bla3”当我查询诸如名称之类的内容时:“某事bla1 b
我需要实现w-shingling (Java 中)比较两个 html 文档的相似性。问题是如何收集和储存木瓦。我们假设 (a,rose,is,a,rose,is,a,rose) 是这些文档之一。我想我
我们有一个符合 OData 的 API,可以将部分全文搜索需求委托(delegate)给 Elasticsearch 集群。 由于 OData 表达式可能变得非常复杂,因此我们决定将它们简单地转换为等
我在 Django 应用程序中使用 Elasticsearch 进行全文搜索。我正在使用 pypi 中的 elastic_dsl 库与集群交互。我正在尝试在分析器中实现瓦状过滤器。我相信我已经让它使用
如何称呼 Python DSL 中的带状疱疹? 这是一个简单的示例,在“姓名”字段中搜索一个短语,在“姓氏”字段中搜索另一个短语。 import json from elasticsearch imp
我将 lucene 4.4 版与这些分析器一起使用: worddelimeter, patternFilter, synonyms, lowercase, stopwords, kStemFilter
在我正在构建的索引中,我对运行查询感兴趣,然后(使用构面)返回该查询的带状疱疹。这是我在文本上使用的分析器: { "settings": { "analysis": { "an
我是一名优秀的程序员,十分优秀!