在映射为not_analyzed后获得完全匹配

时间:2017-09-13 03:39:38

标签: elasticsearch

我的弹性搜索类型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"
      }
    }
  }
}

我正在使用目录索引进行分析,因为我只想给出最后一个文件夹并获得结果,但是当我想搜索特定目录时,我需要给出整个路径,因为在两个路径中可以有相同的文件夹。这里的问题是,因为它被分析它将是所有数据而不是我想要的特定数据。

这里的问题是我想像分析和未分析那样行事。有没有办法呢?

2 个答案:

答案 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.rawnot_analyzed会将其视为let [entityTypes, entityValues] = await Promise.all([ db.runSqlQuery(command1), // First SQL call db.runSqlQuery(command2), // Second SQL call; Exception here ]); Refer this