代码之家  ›  专栏  ›  技术社区  ›  Jonathan Rys

Elasticsearch中的搜索周期和以连字符分隔的字段

  •  0
  • Jonathan Rys  · 技术社区  · 7 年前

    我试图找到一种方法,使用Elasticsearch来查询一个以句号和连字符分隔的字段。

    id    text        tag
    ====================================
    1     some-text   A.B.c3
    2     more. text  A.B-C.c4
    3     even more.  B.A-32.D-24.f9
    


    我首先使用ES进行搜索的核心原因是我想查询 text 领域那部分太棒了!


    但是,(我想)我想要 tag

    A.B.c3            1
    A.B-C.c4          2
    B.A-C2.D-24.f9    3
    

    然后,我想搜索 标签 像这样的领域:

    { "query": {
          "prefix" : { "tag" : "A.B" }
        }
    }
    

    并返回查询 id /行/文档1和2。

    基本上,我希望查询与此真值表中的索引匹配:

    "A." = 1, 2
    "A-" = 3
    

    我如何实现这两个目标?” A.

    如果这些比赛发生在比赛开始的时候,我想把它们的权重提高一些 标签 字段(如果可能)。

    我该怎么做,或者Elasticsearch不是适合这份工作的工具?Elasticsearch似乎非常适合在通常分隔的英文文本上进行文本字段比较,但基于标记的搜索似乎要困难得多。

    更新:

    2 回复  |  直到 7 年前
        1
  •  1
  •   Kamal Kunjapur    7 年前

    这可以通过 N-Gram

    根据您所提供的内容,我创建了相应的映射、文档和一个示例查询,为您提供所需内容。

    映射

    PUT idtesttag
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "my_analyzer": {
              "tokenizer": "my_tokenizer"
            }
          },
          "tokenizer": {
            "my_tokenizer": {
              "type": "ngram",
              "min_gram": 2,
              "max_gram": 5
            }
          }
        }
      },
      "mappings": {
        "mydocs": {
          "properties": {
            "id": {
              "type": "long"
            },
            "text": {
              "type": "text",
              "analyzer": "my_analyzer"
            },
            "tag": {
              "type": "text",
              "analyzer": "my_analyzer"
            }
          }
        }
      }
    }
    

    id = 1 有一个标签 A.B

     A. -> 1
     .B -> 1
    A.B -> 1
    

    因此,如果您的查询包含这三个单词中的任何一个,那么您的文档 id=1 将被退回。

    POST idtesttag/mydocs/1
    {
      "id": 1,
      "text": "some-text",
      "tag": "A.B.c3"
    }
    
    POST idtesttag/mydocs/2
    {
      "id": 2,
      "text": "more. text",
      "tag": "A.B-C.c4"
    }
    
    POST idtesttag/mydocs/3
    {
      "id": 3,
      "text": "even more.",
      "tag": "B.A-32.D-24.f9"
    }
    
    POST idtesttag/mydocs/4
    {
      "id": 3,
      "text": "even more.",
      "tag": "B.A.B-32.D-24.f9"
    }
    

    示例查询

    POST idtesttag/_search
    {
      "query": {
        "match": {
          "tag": "A.B"
        }
      }
    }
    

    查询响应

    {
      "took": 139,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
      },
      "hits": {
        "total": 3,
        "max_score": 0.8630463,
        "hits": [
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "1",
            "_score": 0.8630463,
            "_source": {
              "id": 1,
              "text": "some-text",
              "tag": "A.B.c3"
            }
          },
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "2",
            "_score": 0.66078395,
            "_source": {
              "id": 2,
              "text": "more. text",
              "tag": "A.B-C.c4"
            }
          },
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "4",
            "_score": 0.46659434,
            "_source": {
              "id": 3,
              "text": "even more.",
              "tag": "B.A.B-32.D-24.f9"
            }
          }
        ]
      }
    }
    

    请注意,文档1、2和4在响应中返回。这个 document 4 而文件 1 & 2 我们才刚开始。

    还要注意分数值的显示方式。

    基于hypen的Boosting

    现在关于基于 hypen 性格,我建议你 Bool 随附查询 Regex Query with Boosting . 下面是我提出的示例查询。

    请注意,为了简单起见,我添加了regex,只有在hypen紧随其后的情况下,它才会提高性能 A.B .

    POST idtesttag/_search
    {
      "query": {
        "bool": {
          "must" : {
            "match" : { "tag" : "A.B" }
          },
          "should": [
            {
              "regexp": {
                "tag": {
                  "value": "A.B-.*",
                  "boost": 3
                }
              }
            }
          ]
        }
      }
    }
    

    {
      "took": 2,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
      },
      "hits": {
        "total": 3,
        "max_score": 3.660784,
        "hits": [
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "2",
            "_score": 3.660784,
            "_source": {
              "id": 2,
              "text": "more. text",
              "tag": "A.B-C.c4"
            }
          },
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "4",
            "_score": 3.4665942,
            "_source": {
              "id": 3,
              "text": "even more.",
              "tag": "B.A.B-32.D-24.f9"
            }
          },
          {
            "_index": "idtesttag",
            "_type": "mydocs",
            "_id": "1",
            "_score": 0.8630463,
            "_source": {
              "id": 1,
              "text": "some-text",
              "tag": "A.B.c3"
            }
          }
        ]
      }
    }
    

    只要确保你的测试是彻底的,因为这一切都是为了影响分数&请确保使用DEV/TEST弹性索引中摄取的prod数据执行此操作。

        2
  •  0
  •   Community Mohan Dere    6 年前

    但是,(我想)我希望标签像这样出现在倒排索引中(我可能不会考虑大小写,只是为了举例说明):

    根据您在post reg中的描述。“标签”字段,这是我的2美分。

    我将您的“标签”字段定义为多个字段:

    • 为聚合键入“关键字”
    • 使用自定义分析器(可能使用“空白”标记器和“边缘ngram”标记过滤器)键入“文本”进行搜索

    (如果不需要聚合,则只需使用自定义分析器定义“文本”类型字段)

    仅供参考 Analyze API 将向您展示ES如何处理您的“标记”数据,并将帮助您定义满足您需求的映射。