【问题标题】:How to allow searching with spacial character in Elasticsearch using Attachment plugin?如何允许使用附件插件在 Elasticsearch 中使用特殊字符进行搜索?
【发布时间】:2020-05-19 05:36:33
【问题描述】:

我正在开发 Spring Boot - JHipster 基础项目。

我正在使用带有附件插件的 Elasticsearch 6.8.6。 其中,内容字段包含我的文档的数据。

现在,当我搜索“192.168.31.167”时,它会给出适当的结果。但是,当我搜索这个“192.168.31.167:9200”时,它会给出一个空结果。

简而言之,它不适用于空格字符。 有人可以指导我。如何处理?

映射:

{
  "document" : {
    "mappings" : {
      "doc" : {
        "properties" : {
          "attachment" : {
            "properties" : {
              "content" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              },
              "content_length" : {
                "type" : "long"
              },
              "content_type" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              }
            }
          },
          "content" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "createdDate" : {
            "type" : "date"
          },
          "holder" : {
            "type" : "long"
          },
          "id" : {
            "type" : "long"
          },
          "name" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          },
          "tag" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            }
          }
        }
      }
    }
  }
}

虚拟数据:

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "document",
        "_type" : "doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "createdDate" : "2020-05-19T03:56:36+0000",
          "attachment" : {
            "content_type" : "text/plain; charset=ISO-8859-1",
            "content" : "version: '2'\nservices:\n  docy-kibana:\n    image: docker.elastic.co/kibana/kibana:6.8.6\n    ports:\n      - 5601:5601\n\n    environment:\n      SERVER_NAME: kibana.example.org\n      ELASTICSEARCH_HOSTS: http://192.168.31.167:9200/\n      XPACK_MONITORING_ENABLED: ${true}\n#      XPACK_ENCRYPTEDSAVEDOBJECTS.ENCRYPTIONKEY: test\n      XPACK_MONITORING_UI_CONTAINER_ELASTICSEARCH_ENABLED: ${true}",
            "content_length" : 390
          },
          "name" : "kibana_3_202005190926.yml",
          "holder" : 3,
          "id" : 1,
          "tag" : "configuration",
          "content" : "dmVyc2lvbjogJzInCnNlcnZpY2VzOgogIGRvY3kta2liYW5hOgogICAgaW1hZ2U6IGRvY2tlci5lbGFzdGljLmNvL2tpYmFuYS9raWJhbmE6Ni44LjYKICAgIHBvcnRzOgogICAgICAtIDU2MDE6NTYwMQoKICAgIGVudmlyb25tZW50OgogICAgICBTRVJWRVJfTkFNRToga2liYW5hLmV4YW1wbGUub3JnCiAgICAgIEVMQVNUSUNTRUFSQ0hfSE9TVFM6IGh0dHA6Ly8xOTIuMTY4LjMxLjE2Nzo5MjAwLwogICAgICBYUEFDS19NT05JVE9SSU5HX0VOQUJMRUQ6ICR7dHJ1ZX0KIyAgICAgIFhQQUNLX0VOQ1JZUFRFRFNBVkVET0JKRUNUUy5FTkNSWVBUSU9OS0VZOiB0ZXN0CiAgICAgIFhQQUNLX01PTklUT1JJTkdfVUlfQ09OVEFJTkVSX0VMQVNUSUNTRUFSQ0hfRU5BQkxFRDogJHt0cnVlfQo="
        }
      }
    ]
  }
}

代码生成的Elasticsearch请求:

{
  "bool" : {
    "must" : [
      {
        "bool" : {
          "should" : [
            {
              "query_string" : {
                "query" : "*192.168.31.167:9200*",
                "fields" : [
                  "content^1.0",
                  "name^2.0",
                  "tag^3.0"
                ],
                "type" : "best_fields",
                "default_operator" : "or",
                "max_determinized_states" : 10000,
                "enable_position_increments" : true,
                "fuzziness" : "AUTO",
                "fuzzy_prefix_length" : 0,
                "fuzzy_max_expansions" : 50,
                "phrase_slop" : 0,
                "analyze_wildcard" : true,
                "escape" : false,
                "auto_generate_synonyms_phrase_query" : true,
                "fuzzy_transpositions" : true,
                "boost" : 1.0
              }
            },
            {
              "wildcard" : {
                "attachment.content" : {
                  "wildcard" : "*192.168.31.167:9200*",
                  "boost" : 1.0
                }
              }
            }
          ],
          "adjust_pure_negative" : true,
          "boost" : 1.0
        }
      },
      {
        "bool" : {
          "should" : [
            {
              "wildcard" : {
                "tag.keyword" : {
                  "wildcard" : "*information*",
                  "boost" : 1.0
                }
              }
            },
            {
              "wildcard" : {
                "tag.keyword" : {
                  "wildcard" : "*user*",
                  "boost" : 1.0
                }
              }
            }
          ],
          "adjust_pure_negative" : true,
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

【问题讨论】:

  • 您应该提供一种方法让我们重新创建问题(映射、查询、示例文档等)。这里有太多的未知数。
  • 抱歉,问题已更新。
  • 您可以查看此线程,它提供了从文本正文中提取 ip:port 的解决方案:stackoverflow.com/a/34986008/4604579。我将继续使用该分析器添加另一个子字段并在该字段上进行搜索。
  • 值得注意的是,如果您要按照上述线程中的建议选择分析器方式,我很乐意确保该插件适用于 ES 6.8。
  • @DhwanilPatel 很长时间以来,您都没有接受并支持我的答案,如果您的问题得到解决,如果您能接受并支持答案,那就太好了

标签: elasticsearch


【解决方案1】:

问题:

您正在使用text 字段查询使用standard 分析器并在: 上拆分文本的数据,如下所示analyze API 调用:

POST /_analyze
{
    "text" : "127.0.0.1:9200",
    "analyzer" : "standard"
}

生成的令牌

{
    "tokens": [
        {
            "token": "127.0.0.1",
            "start_offset": 0,
            "end_offset": 9,
            "type": "<NUM>",
            "position": 0
        },
        {
            "token": "9200",
            "start_offset": 10,
            "end_offset": 14,
            "type": "<NUM>",
            "position": 1
        }
    ]
}

解决方案 - 1

未优化(对较大索引的通配符查询可能会导致严重的性能问题),但由于您已经在使用通配符,它​​可以在不更改分析器并重新索引整个数据的情况下工作(减少开销):

使用.keyword这些文本字段上可用的字段,不会将文本分成2个标记,如下所示

{
    "tokens": [
        {
            "token": "127.0.0.1:9200",
            "start_offset": 0,
            "end_offset": 14,
            "type": "word",
            "position": 0
        }
    ]
}

您可以添加.keyword,如下图:

             "content.keyword^1.0",
              "name.keyword^2.0",
              "tag.keyword^3.0"

解决方案- 2

请参阅@val 评论中提到的解决方案,这将涉及创建自定义分析器并重新索引整个数据,这将在索引中创建预期的标记,然后在不使用昂贵的正则表达式的情况下搜索它们。 这将在大型数据集上显着提高性能,但使用新的分析器和查询重新索引整个数据会产生一次开销。

请选择更适合您业务需求的方法。

【讨论】:

  • 问题是关键字字段没有被分析,并且 ip:port 位于字符串的中间,所以它需要一个正则表达式查询(或通配符查询字符串),这将提供很差的大量数据的性能。但它可能适用于少量数据
  • @Val 完全同意,但他已经这样做了,他甚至使用领先的通配符 *
  • @Val,哦,是的,没有注意到你已经有了答案,那么这对我来说很容易,我马上更新这个
  • @DhwanilPatel 是的,您也可以使用 n-gram 标记器,但请注意它可以创建大量标记并增加您的索引大小,如果您没有大量标记,这可能会导致性能问题elasticsearch 中的文档。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-31
  • 2013-04-02
  • 2014-04-25
  • 2011-07-08
  • 2017-12-31
  • 2020-10-15
相关资源
最近更新 更多