【发布时间】:2015-09-05 01:43:11
【问题描述】:
我正在开发一个会员管理计划,我们希望使用 Elasticsearch 作为搜索引擎。在这一点上,我们在索引某些字段时遇到了问题,因为它们会在 _all 字段上生成一个“巨大的术语”错误。
我们的设置:
curl -XGET 'http://localhost:9200/my_index?pretty=true'
{
"my_index" : {
"aliases" : { },
"mappings" : {
"Memberships" : {
"_all" : {
"analyzer" : "keylower"
},
"properties" : {
"Amount" : {
"type" : "float"
},
"Members" : {
"type" : "nested",
"properties" : {
"Startdate membership" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"Enddate membership" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"Members" : {
"type" : "string",
"analyzer" : "keylower"
}
}
},
"Membership name" : {
"type" : "string",
"analyzer" : "keylower"
},
"Description" : {
"type" : "string",
"analyzer" : "keylower"
},
"elementId" : {
"type" : "integer"
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1441310632366",
"number_of_shards" : "1",
"analysis" : {
"filter" : {
"my_char_filter" : {
"type" : "asciifolding",
"preserve_original" : "true"
}
},
"analyzer" : {
"keylower" : {
"filter" : [ "lowercase", "my_char_filter" ],
"tokenizer" : "keyword"
}
}
},
"number_of_replicas" : "1",
"version" : {
"created" : "1040599"
},
"uuid" : "nn16-9cTQ7Gn9NMBlFxHsw"
}
},
"warmers" : { }
}
}
我们使用 keylower-analyzer,因为我们不希望全名被空格分割。这是因为我们希望能够在 _all 字段以及 'Members' 字段中搜索 'john johnson'。
“成员”字段可以包含多个成员,这就是问题开始的地方。当该字段仅包含几个成员时(如下例所示),没有问题。但是,该字段可能包含数百或数千个成员,这就是我们得到 immens term 错误的时候。
curl 'http://localhost:9200/my_index/_search?pretty=true&q=*:*'
{
"took":1,
"timed_out":false,
"_shards":{
"total":1,
"successful":1,
"failed":0
},
"hits":{
"total":1,
"max_score":1.0,
"hits":[
{
"_index":"my_index",
"_type":"Memberships",
"_id":"15",
"_score":1.0,
"_source":{
"elementId":[
"15"
],
"Membership name":[
"My membership"
],
"Amount":[
"100"
],
"Description":[
"This is the description."
],
"Members":[
{
"Members":"John Johnson",
"Startdate membership":"2015-01-09",
"Enddate membership":"2015-09-03"
},
{
"Members":"Pete Peterson",
"Startdate membership":"2015-09-09"
},
{
"Members":"Santa Claus",
"Startdate membership":"2015-09-16"
}
]
}
}
]
}
}
注意:上面的例子有效!只有当“成员”字段包含(很多)更多成员时,我们才会收到错误消息。我们得到的错误是:
"error":"IllegalArgumentException[文档包含至少一个 field=\"_all\" 中的巨大术语(其 UTF8 编码比 最大长度 32766),所有这些都被跳过了。请更正 分析仪不产生这样的条款。第一个巨大的前缀 术语是:'[...]...',原始消息:字节最多可以是 32766 in 长度;得到 106807];嵌套:MaxBytesLengthExceededException[字节可以 长度最多为 32766;得到 106807]; " "状态":500
我们只在 _all 字段上收到此错误,而不是在原始成员字段上。使用ignore_above,不再可以在全名的_all 字段中进行搜索。使用标准分析器,如果我搜索“Santa Johnson”,我会找到这个文档,因为 _all-fields 有一个标记“Santa”和“Johnson”。这就是我对这些字段使用 keylower 的原因。
我想要的是一个分析器,它可以对字段进行标记,但不会分解字段本身的值。现在发生的情况是,整个字段“成员”被作为一个令牌提供,包括子字段。 (因此,上面示例中的令牌将是:
- John Johnson 2015-01-09 2015-09-03 Pete Peterson 2015-09-09 圣诞老人 2015-09-16
是否可以对这些字段进行标记,使每个字段都作为单独的标记提供给 _all,但又不分解字段本身的值?这样令牌将是:
- 约翰·约翰逊
- 2015-01-09
- 2015-09-03
- 皮特·彼得森
- 2015-09-09
- 圣诞老人
- 2015-09-16
注意:我们使用 Elasticsearch php 库。
【问题讨论】:
-
This answer 应该可以帮到你。
-
只想补充@Val 所说的内容。除了将
_all字段视为单个非标记化 blob 并使用非常昂贵的子字符串搜索之外,还有更好的替代方法。例如,您可以在 _all 字段上使用标准分析器,然后搜索短语“John Johnson”。或者您可以使用单个过滤器索引 _all 并使用正常匹配查询搜索 2 或 3 个单词短语。也许,如果您可以用更完整的要求更新您的问题,我们将能够为您提供更好、性能更高的解决方案。 -
@imotov 我已经编辑了这个问题,包括我们不使用默认分析器和 ignore_above 的原因。
-
@wjhulzebosch 你没有回答为什么不能使用标准分析器和phrase search
-
@imotov 如果我对匹配/短语查询的理解是正确的,我做到了:我不想在搜索“Santa Johnson”时找到这个文档,但是当我使用默认分析器和然后执行这个搜索,这个文档会弹出,因为它有一个标记'Santa'和'Johnson'。也许我现在错了?
标签: php elasticsearch