在 Elasticsearch 中搜索带连字符的文本

Searching for hyphened text in Elasticsearch

我正在 elasticsearch 中存储一个 'Payment Reference Number'。

它的布局是例如:2-4-3-6358445698191095312-4-2-635844533758635433等等

我希望能够通过

按付款参考号搜索文件
  1. 使用 'whole' 参考号搜索,例如输入 2-4-2-635844533758635433
  2. 任何'part'的参考号来自'start'。例如。 2-4-2-63(..所以只有 return 示例中的第二个)

注意:我不想搜索 'in the middle' 或 'at the end' 等。只从头开始。

无论如何,连字符让我感到困惑。

问题

1) 我不确定是否应该像

这样在映射中删除它们
"char_filter" : {
    "removeHyphen" : {
        "type" : "mapping",
            "mappings" : ["-=>"]
        }
    },

还是不行。我从来没有以这种方式使用映射,所以不确定是否有必要。

2) 我想我需要一个 'ngrams' 过滤器,因为我希望能够从存在中搜索参考编号的一部分。我觉得像

"partial_word":{
    "filter":[
        "standard",
            "lowercase",
            "name_ngrams"
        ],
    "type":"custom",
    "tokenizer":"whitespace"
},

和过滤器

"name_ngrams":{
    "side":"front",
        "max_gram":50,
        "min_gram":2,
    "type":"edgeNGram"
},

我不确定如何将它们放在一起但是

"paymentReference":{
    "type":"string",
    "analyzer": "??",
    "fields":{
        "partial":{
            "search_analyzer":"???",
            "index_analyzer":"partial_word",
            "type":"string"
        }
    }
}

在第二个搜索案例中,我尝试过的一切似乎总是 'break'。

如果我这样做 'localhost:9200/orders/_analyze?field=paymentReference&pretty=1' -d "2-4-2-635844533758635433" 它总是打破连字符,因为它是自己的标记和 returns 例如所有带 2- 的文档都是 'alot'!而不是我在搜索 2-4-2-6

时想要的

有人可以告诉我如何为我要实现的两种搜索类型映射此字段吗?

更新-回答

实际上是 Val 在下面所说的。我只是稍微更改了映射,以便更具体地重新分析分析器,而且我不需要索引主字符串,因为我只查询部分字符串。

映射

"paymentReference":{
    "type": "string",
    "index":"not_analyzed",
    "fields": {
        "partial": {
            "search_analyzer":"payment_ref",
            "index_analyzer":"payment_ref",
            "type":"string"
        }
    }
}

分析仪

"payment_ref": {
    "type": "custom",
    "filter": [
        "lowercase",
        "name_ngrams"
    ],
    "tokenizer": "keyword"
}

过滤器

"name_ngrams":{
    "side":"front",
    "max_gram":50,
    "min_gram":2,
    "type":"edgeNGram"
},

您不需要为此使用映射字符过滤器。

您使用 Edge NGram 标记过滤器的方向正确,因为您只需要能够搜索前缀。我会改用 keyword 分词器来确保该术语被视为一个整体。所以设置方法是这样的:

curl -XPUT localhost:9200/orders -d '{
  "settings": {
    "analysis": {
      "analyzer": {
        "partial_word": {
          "type": "custom",
          "filter": [
            "lowercase",
            "ngram_filter"
          ],
          "tokenizer": "keyword"
        }
      },
      "filter": {
        "ngram_filter": {
          "type": "edgeNGram",
          "min_gram": 2,
          "max_gram": 50
        }
      }
    }
  },
  "mappings": {
    "order": {
      "properties": {
        "paymentReference": {
          "type": "string",
          "fields": {
            "partial": {
              "analyzer": "partial_word",
              "type": "string"
            }
          }
        }
      }
    }
  }
}'

然后您可以分析将要索引到您的 paymentReference.partial 字段的内容:

curl -XGET 'localhost:9205/payments/_analyze?field=paymentReference.partial&pretty=1' -d "2-4-2-635844533758635433"

你得到的正是你想要的,即所有前缀:

{
  "tokens" : [ {
    "token" : "2-",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-6",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-63",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-635",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-6358",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "2-4-2-63584",
    "start_offset" : 0,
    "end_offset" : 24,
    "type" : "word",
    "position" : 1
  }, {
  ...

终于可以搜索任意前缀了:

curl -XGET localhost:9200/orders/order/_search?q=paymentReference.partial:2-4-3

不确定通配符搜索是否符合您的需要。我定义自定义过滤器并设置 preserve_original 并生成错误的数字部分。这是示例代码:

PUT test1
{
  "settings" : {
    "analysis" : {
      "analyzer" : {
        "myAnalyzer" : {
          "type" : "custom",
          "tokenizer" : "whitespace",
          "filter" : [ "dont_split_on_numerics" ]
        }
      },
      "filter" : {
        "dont_split_on_numerics" : {
          "type" : "word_delimiter",
          "preserve_original": true,
          "generate_number_parts" : false
        }
      }
    }
  },
  "mappings": {
    "type_one": {
      "properties": {
        "title": { 
          "type": "text",
          "analyzer": "standard" 
        }
      }
    },
    "type_two": {
      "properties": {
        "raw": { 
          "type": "text",
          "analyzer": "myAnalyzer" 
        }
      }
    }
  }
}

POST test1/type_two/1
{
  "raw": "2-345-6789" 
}

GET test1/type_two/_search
{
  "query": {
    "wildcard": {
      "raw": "2-345-67*" 
    }
  }
}