我的弹性搜索类型I映射如下,
mappings": {
"jardata": {
"properties": {
"groupID": {
"index": "not_analyzed",
"type": "string"
},
"artifactID": {
"index": "not_analyzed",
"type": "string"
},
"directory": {
"type": "string"
},
"jarFileName": {
"index": "not_analyzed",
"type": "string"
},
"version": {
"index": "not_analyzed",
"type": "string"
}
}
}
}
我正在使用目录索引进行分析,因为我只想给出最后一个文件夹并获得结果,但是当我想搜索特定目录时,我需要给出整个路径,因为在两个路径中可以有相同的文件夹。这里的问题是,因为它被分析它将是所有数据而不是我想要的特定数据。
这里的问题是我想像分析和未分析那样行事。有没有办法呢?
答案 0 :(得分:2)
我们假设您已将以下文档编入索引:
{
"directory": "/home/docs/public"
}
标准分析器在您的情况下还不够,因为它会在编制索引时创建以下术语:
[home, docs, public]
请注意,它错过了[/home/docs/public]
令牌 - 像" /"在这里充当分隔符。
一种解决方案可能是在punctuation
列表中使用带有token_chars
字符类的NGram标记生成器。 Elasticsearch会对待" /"因为它是一个字母或数字。这将允许使用以下标记进行搜索:
[/hom, /home, ..., /home/docs/publi, /home/docs/public, ..., /docs/public, etc...]
索引映射:
{
"settings": {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"type": "ngram",
"min_gram": 4,
"max_gram": 18,
"token_chars": [
"letter",
"digit",
"punctuation"
]
}
}
}
},
"mappings": {
"jardata": {
"properties": {
"directory": {
"type": "string",
"analyzer": "ngram_analyzer"
}
}
}
}
}
现在两个搜索查询:
{
"query": {
"bool" : {
"must" : {
"term" : {
"directory": "/docs/private"
}
}
}
}
}
和
{
"query": {
"bool" : {
"must" : {
"term" : {
"directory": "/home/docs/private"
}
}
}
}
}
将在结果中提供索引文档。
您必须考虑的一件事是"max_gram"
设置中指定的令牌的最大长度。如果是目录路径,可能需要更长时间。
替代解决方案是使用Whitespace tokenizer,将短语分解为仅在空格上的术语,并NGram filter使用以下映射:
{
"settings": {
"analysis": {
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": 4,
"max_gram": 20
}
},
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"filter": [
"lowercase",
"ngram_filter"
]
}
}
}
},
"mappings": {
"jardata": {
"properties": {
"directory": {
"type": "string",
"analyzer": "my_analyzer"
}
}
}
}
}
答案 1 :(得分:2)
更新directory
字段的映射以包含raw
字段,如下所示:
"directory": {
"type": "string",
"fields": {
"raw": {
"index": "not_analyzed",
"type": "string"
}
}
}
修改您的查询以包含directory.raw
,not_analyzed
会将其视为let [entityTypes, entityValues] = await Promise.all([
db.runSqlQuery(command1), // First SQL call
db.runSqlQuery(command2), // Second SQL call; Exception here
]);
。 Refer this