资讯专栏INFORMATION COLUMN

elasticsearch学习笔记高级篇(十二)——掌握phrase matching搜索技术

kgbook / 1910人阅读

摘要:什么是近似搜索假设有两个句子适用搜索只能搜索到包含和的但是不知道和是不是离得很近。实际举一个例子对于假设我们要用匹配到。加上之后虽然是近似匹配可以搜索到很多结果,但是距离越近的会优先返回,也就是相关度分数就会越高。

1、什么是近似搜索

假设有两个句子

java is my favourite programming langurage, and I also think spark is a very good big data system.

java spark are very related, because scala is spark"s programming langurage and scala is also based on jvm like java. 

适用match query 搜索java spark

{
    {
        "match": {
            "content": "java spark"
        }
    }
}

match query 只能搜索到包含java和spark的document,但是不知道java和spark是不是离得很近。
假设我们想要java和spark离得很近的document优先返回,就要给它一个更高的relevance score,这就涉及到了proximity match近似匹配。
下面给出要实现的两个需求:
(1)搜索java spark,就靠在一起,中间不能插入任何其它字符
(2)搜索java spark,要求java和spark两个单词靠的越近,doc的分数越高,排名越靠前

2、match phrase

准备数据:

PUT /test_index/_create/1
{
  "content": "java is my favourite programming language, and I also think spark is a very good big data system."
}
PUT /test_index/_create/2
{
  "content": "java spark are very related, because scala is spark"s programming language and scala is also based on jvm like java."
}

对于需求1 搜索java spark,就靠在一起,中间不能插入任何其它字符:
使用match query搜索无法实现

GET /test_index/_search
{
  "query": {
    "match": {
      "content": "java spark"
    }
  }
}

结果:

{
  "took" : 16,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.4255141,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.4255141,
        "_source" : {
          "content" : "java spark are very related, because scala is spark"s programming language and scala is also based on jvm like java."
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.37266707,
        "_source" : {
          "content" : "java is my favourite programming language, and I also think spark is a very good big data system."
        }
      }
    ]
  }
}

使用match phrase搜索就可以实现

GET /test_index/_search
{
  "query": {
    "match_phrase": {
      "content": "java spark"
    }
  }
}

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.35695744,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.35695744,
        "_source" : {
          "content" : "java spark are very related, because scala is spark"s programming language and scala is also based on jvm like java."
        }
      }
    ]
  }
}
3、term position

假设我们有两个document

doc1: hello world, java spark
doc2: hi, spark java

hello doc1(0)
world doc1(1)
java  doc1(2) doc2(2)
spark doc1(3) doc2(1)

position详情如下:

GET /_analyze
{
  "text": ["hello world, java spark"],
  "analyzer": "standard"
}
{
  "tokens" : [
    {
      "token" : "hello",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "",
      "position" : 0
    },
    {
      "token" : "world",
      "start_offset" : 6,
      "end_offset" : 11,
      "type" : "",
      "position" : 1
    },
    {
      "token" : "java",
      "start_offset" : 13,
      "end_offset" : 17,
      "type" : "",
      "position" : 2
    },
    {
      "token" : "spark",
      "start_offset" : 18,
      "end_offset" : 23,
      "type" : "",
      "position" : 3
    }
  ]
}
GET /_analyze
{
  "text": ["hi, spark java"],
  "analyzer": "standard"
}
{
  "tokens" : [
    {
      "token" : "hi",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "",
      "position" : 0
    },
    {
      "token" : "spark",
      "start_offset" : 4,
      "end_offset" : 9,
      "type" : "",
      "position" : 1
    },
    {
      "token" : "java",
      "start_offset" : 10,
      "end_offset" : 14,
      "type" : "",
      "position" : 2
    }
  ]
}
4、match phrase基本原理
索引中的position,match_phrase

hello world, java spark        doc1
hi, spark java                doc2

hello         doc1(0)        
wolrd        doc1(1)
java        doc1(2) doc2(2)
spark        doc1(3) doc2(1)

使用match_phrase查询要求找到每个term都在一个共有的那些doc,就是要求一个doc,必须要包含查询的每个term,并且满足位置运算。

doc1 --> java和spark --> spark position恰巧比java大1 --> java的position是2,spark的position是3,恰好满足条件
doc1符合条件
doc2 --> java和spark --> java position是2,spark position是1,spark position比java position小1,而不是大1 --> 光是position就不满足,那么doc2不匹配
doc2不符合条件
5、slop参数

含义:query string搜索文本中的几个term,要经过几次移动才能与一个document匹配,这个移动的次数就是slop。
实际举一个例子:
对于hello world, java is very good, spark is also very good. 假设我们要用match phrase 匹配到java spark。可以发现直接进行查询会查不到

PUT /test_index/_create/1
{
  "content": "hello world, java is very good, spark is also very good."
}

GET /test_index/_search
{
  "query": {
    "match_phrase": {
      "content": "java spark"
    }
  }
}
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

此时使用

GET /_analyze
{
  "text": ["hello world, java is very good, spark is also very good."],
  "analyzer": "standard"
}

结果:

{
  "tokens" : [
    {
      "token" : "hello",
      "start_offset" : 0,
      "end_offset" : 5,
      "type" : "",
      "position" : 0
    },
    {
      "token" : "world",
      "start_offset" : 6,
      "end_offset" : 11,
      "type" : "",
      "position" : 1
    },
    {
      "token" : "java",
      "start_offset" : 13,
      "end_offset" : 17,
      "type" : "",
      "position" : 2
    },
    {
      "token" : "is",
      "start_offset" : 18,
      "end_offset" : 20,
      "type" : "",
      "position" : 3
    },
    {
      "token" : "very",
      "start_offset" : 21,
      "end_offset" : 25,
      "type" : "",
      "position" : 4
    },
    {
      "token" : "good",
      "start_offset" : 26,
      "end_offset" : 30,
      "type" : "",
      "position" : 5
    },
    {
      "token" : "spark",
      "start_offset" : 32,
      "end_offset" : 37,
      "type" : "",
      "position" : 6
    },
    {
      "token" : "is",
      "start_offset" : 38,
      "end_offset" : 40,
      "type" : "",
      "position" : 7
    },
    {
      "token" : "also",
      "start_offset" : 41,
      "end_offset" : 45,
      "type" : "",
      "position" : 8
    },
    {
      "token" : "very",
      "start_offset" : 46,
      "end_offset" : 50,
      "type" : "",
      "position" : 9
    },
    {
      "token" : "good",
      "start_offset" : 51,
      "end_offset" : 55,
      "type" : "",
      "position" : 10
    }
  ]
}
java        is        very        good        spark        is

java        spark
java        -->        spark
java                -->            spark
java                            -->            spark

可以发现java的position是2,spark的position是6,那么我们只需要设置slop大于等于3(也就是移动3词就可以了)就可以搜到了

GET /test_index/_search
{
  "query": {
    "match_phrase": {
      "content": {
        "query": "java spark",
        "slop": 3
      }
    }
  }
}

结果:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.21824157,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.21824157,
        "_source" : {
          "content" : "hello world, java is very good, spark is also very good."
        }
      }
    ]
  }
}

此时加上slop的match phrase就是proximity match近似匹配了。加上slop之后虽然是近似匹配可以搜索到很多结果,但是距离越近的会优先返回,也就是相关度分数就会越高。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/34521.html

相关文章

  • elasticsearch学习笔记(三十二)——Elasticsearch 解密query、fetc

    摘要:注意这里千万不要理解成每个都是返回条数据。这样理解是错误的下面做一下详细的分析请求首先可能是打到一个不包含这个的的上去,这个就是一个协调节点,那么这个就会将搜索请求转发到的三个所在的上去。 query pharse 基本原理:(1)搜索请求发送到某一个coordinate node协调节点,会构建一个priority queue,长度以paging操作from和size为准,默认是10...

    hlcc 评论0 收藏0
  • ElasticSearch 学习笔记 - 8. 查询

    摘要:值是与查询所匹配文档的的最大值。部分告诉我们在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。他们了解如何分析被查询的字段,并在执行之前将每个字段的分析器或应用于查询字符串。 1、概念 映射(Mapping)描述数据在每个字段内如何存储 分析(Analysis) 全文是如何处理使之可以被搜索的 领域特定查询语言(Query DSL) Elasticsearch 中强大灵活...

    Brenner 评论0 收藏0
  • elasticsearch学习笔记(六)——快速入门案例实战之电商网站商品管理:多种搜索方式

    摘要:但是如果查询请求很复杂,就很难去构建搜索条件,在生产环境中很少使用。但是要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配上了,作为结果返回。 简单介绍一下ES的多种搜索方式 1、query string search 格式: GET /{index}/_search GET /product/_search { took : 1, timed_out ...

    williamwen1986 评论0 收藏0
  • Elasticsearch * 入门

    摘要:和使用倒排索引的数据结构来达到相同目的。无需配置,只需要添加数据然后开始搜索分布式的特性你不需要知道任何关于分布式系统分片集群发现或者其他大量的分布式概念。致力于隐藏分布式系统的复杂性。 Elasticsearch * 入门 1. Elasticsearch 前言 Elasticsearch 是一个基于Apache Lucene(TM)的开源搜索引擎、实时分布式搜索和分析引擎。 Lu...

    zengdongbao 评论0 收藏0
  • elasticsearch学习笔记高级(七)——基于term+bool搜索底层原理剖析

    摘要:在上一讲我们可以发现,对于的搜索方式,实现起来可以有多种方式。 在上一讲我们可以发现,对于multi-value的搜索方式,实现起来可以有多种方式。这里就说明一下,实现的方式虽然很多,但是elasticsearch在查询的时候底层都会转换为bool + term的形式 1、普通的match如何转换为term+should { match: { title: ja...

    terro 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<