【Elasticsearch】在Elasticsearch中查询Term Vectors词条向量信息

559 篇文章 545 订阅 ¥79.90 ¥99.00

在这里插入图片描述

1.概述

转载:https://www.cnblogs.com/xing901022/p/5348737.html

关于Term Vectors

额,对于这个专业词汇,暂且就叫做词条向量吧,因为实在想不出什么标准的翻译。说的土一点,也可以理解为关于词的一些统计信息。再说的通俗点,如果想进行全文检索,即从一个词搜索与它相关的文档,总得有个什么记录的信息吧!这就是Term Vectors。

为了不干扰正常的理解,后续就都直接称呼英文的名字吧!免得误导…

先不看这篇文章,如果想要记录全文检索的信息,大家设想一下我们都需要什么内容,就拿"hello world! hello everybody!"来举例。

  • 首先就是这句话都有什么词,“hello”,“world”,“everybody”
  • 然后是这些词关联的文档,因为有可能不止上面这一句话。
  • 最后就是词在文档中的位置,比如hello,出现了两次,就需要记录两份位置信息。

关于TermVector在Lucene中的概念,可以参考网络中的一篇文章

使用_termvectors查询词条向量

在Elasticsearch中可以使用_termvectors查询一个文档中词条相关的信息。这个文档可能是es中存储的,也可能是用户直接在请求体中自定义的。这个方法默认是一个实时的统计信息。

常见的语法如:

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvectors?pretty=true'

也可以指定某个字段,返回这个字段的信息:

curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvectors?fields=text,...'

注意,在Elasticsearch中2.0之前都是使用_termvector,之后都是使用的_termvectors。

返回的信息

使用上面的请求,会返回词条相关的信息:

  • 词条的信息,比如position位置、start_offset开始的偏移值、end_offset结束的偏移值、词条的payLoads(这个主要用于自定义字段的权重)
  • 词条统计,doc_freq、ttf该词出现的次数、term_freq词的频率
  • 字段统计,包含sum_doc_freq该字段中词的数量(去掉重复的数目)、sum_ttf文档中词的数量(包含重复的数目)、doc_count涉及的文档数等等。

默认会返回词条的信息和统计,而不会返回字段的统计。

另外,默认这些统计信息是基于分片的,可以设置dfs为true,返回全部分片的信息,但是会有一定的性能问题,所以不推荐使用。还可以使用field字段对返回的统计信息的字段进行过滤,只返回感兴趣的那部分内容。

5.案例

5.1 例子1:返回存储的Term Vectors信息

首先需要定义一下映射的信息:


PUT /twitter-001/
{
  "mappings": {
      "properties": {
        "text": {
          "type": "text",
          "term_vector": "with_positions_offsets_payloads",
          "store" : true,
          "analyzer" : "fulltext_analyzer"
         },
         "fullname": {
          "type": "text",
          "term_vector": "with_positions_offsets_payloads",
          "analyzer" : "fulltext_analyzer"
        }
      }
  },
  "settings" : {
    "index" : {
      "number_of_shards" : 1,
      "number_of_replicas" : 0
    },
    "analysis": {
      "analyzer": {
        "fulltext_analyzer": {
          "type": "custom",
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "type_as_payload"
          ]
        }
      }
    }
  }
}

然后插入两条数据:

PUT /twitter-001/_doc/1?pretty=true
{
  "fullname" : "John Doe",
  "text" : "twitter test test test "
}

PUT /twitter-001/_doc/2?pretty=true
{
  "fullname" : "Jane Doe",
  "text" : "Another twitter test ..."
}

接下来查询一下文档1的Term Vectors信息:


GET /twitter-001/_doc/1/_termvectors?pretty=true
{
  "fields" : ["text"],
  "offsets" : true,
  "payloads" : true,
  "positions" : true,
  "term_statistics" : true,
  "field_statistics" : true
}


可以得到下面的结果:

{
  "_index" : "twitter-001",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "took" : 69,
  "term_vectors" : {
    "text" : {
      "field_statistics" : {
        "sum_doc_freq" : 6,
        "doc_count" : 2,
        "sum_ttf" : 8
      },
      "terms" : {
        "test" : {
          "doc_freq" : 2,
          "ttf" : 4,
          "term_freq" : 3,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 8,
              "end_offset" : 12,
              "payload" : "d29yZA=="
            },
            {
              "position" : 2,
              "start_offset" : 13,
              "end_offset" : 17,
              "payload" : "d29yZA=="
            },
            {
              "position" : 3,
              "start_offset" : 18,
              "end_offset" : 22,
              "payload" : "d29yZA=="
            }
          ]
        },
        "twitter" : {
          "doc_freq" : 2,
          "ttf" : 2,
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 7,
              "payload" : "d29yZA=="
            }
          ]
        }
      }
    }
  }
}

可以看到上面返回了词条的统计信息,以及字段的统计信息。

5.2 例子2:轻量级生成Term Vectors

虽然这个字段不是显示存储的,但是仍然可以进行词条向量的信息统计。因为ES可以在查询的时候,从_source中分析出相应的内容。

GET /twitter-001/_doc/1/_termvectors?pretty=true
{
  "fields" : ["text", "some_field_without_term_vectors"],
  "offsets" : true,
  "positions" : true,
  "term_statistics" : true,
  "field_statistics" : true
}

关于字段的存储于不存储,可以简单的理解为:

  • 如果字段存储,在ES进行相关的查询时,会直接从存储的字段读取信息
  • 如果字段不存储,ES会从_source中查询分析,提取相应的部分。

由于每次读取操作都是一次的IO,因此如果你不是只针对某个字段、或者_source中的信息太多,那么请优先不存储该字段,即从_source中获取就好。

5.3 例子3:手动自定义的文档统计

ES支持对一个用户自定义的文档进行分析,比如:


GET /twitter-001/_doc/_termvectors
{
  "doc" : {
    "fullname" : "John Doe",
    "text" : "twitter test test test"
  }
}

注意如果这个字段没有预先定义映射,那么会按照默认的映射配置进行分析。 结果如下

{
  "_index" : "twitter-001",
  "_type" : "_doc",
  "_version" : 0,
  "found" : true,
  "took" : 21,
  "term_vectors" : {
    "fullname" : {
      "field_statistics" : {
        "sum_doc_freq" : 4,
        "doc_count" : 2,
        "sum_ttf" : 4
      },
      "terms" : {
        "doe" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 5,
              "end_offset" : 8
            }
          ]
        },
        "john" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 4
            }
          ]
        }
      }
    },
    "text" : {
      "field_statistics" : {
        "sum_doc_freq" : 6,
        "doc_count" : 2,
        "sum_ttf" : 8
      },
      "terms" : {
        "test" : {
          "term_freq" : 3,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 8,
              "end_offset" : 12
            },
            {
              "position" : 2,
              "start_offset" : 13,
              "end_offset" : 17
            },
            {
              "position" : 3,
              "start_offset" : 18,
              "end_offset" : 22
            }
          ]
        },
        "twitter" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 7
            }
          ]
        }
      }
    }
  }
}

5.4 例子4:重新定义分析器

可以使用per_field_analyzer参数定义该字段的分析器,这样每个字段都可以使用不同的分析器,分析其词条向量的信息。如果这个字段已经经过存储,那么会重新生成它的词条向量,如:

GET /twitter-001/_doc/_termvectors
{
  "doc" : {
    "fullname" : "John Doe",
    "text" : "twitter test test test"
  },
  "fields": ["fullname"],
  "per_field_analyzer" : {
    "fullname": "keyword"
  }
}


结果如下

{
  "_index" : "twitter-001",
  "_type" : "_doc",
  "_version" : 0,
  "found" : true,
  "took" : 0,
  "term_vectors" : {
    "fullname" : {
      "field_statistics" : {
        "sum_doc_freq" : 4,
        "doc_count" : 2,
        "sum_ttf" : 4
      },
      "terms" : {
        "John Doe" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 8
            }
          ]
        }
      }
    }
  }
}

5.5 例子5:字段过滤器

在进行词条向量的信息查询时,可以根据自定义的过滤器,返回感兴趣的信息。

常用的过滤器参数如:

max_num_terms 最大的词条数目
min_term_freq 最小的词频,比如忽略那些在字段中出现次数小于一定值的词条。
max_term_freq 最大的词频
min_doc_freq 最小的文档频率,比如忽略那些在文档中出现次数小于一定的值的词条
max_doc_freq 最大的文档频率
min_word_length 忽略的词的最小长度
max_word_length 忽略的词的最大长度

会返回:

{
   "_index": "imdb",
   "_type": "movies",
   "_version": 0,
   "found": true,
   "term_vectors": {
      "plot": {
         "field_statistics": {
            "sum_doc_freq": 3384269,
            "doc_count": 176214,
            "sum_ttf": 3753460
         },
         "terms": {
            "armored": {
               "doc_freq": 27,
               "ttf": 27,
               "term_freq": 1,
               "score": 9.74725
            },
            "industrialist": {
               "doc_freq": 88,
               "ttf": 88,
               "term_freq": 1,
               "score": 8.590818
            },
            "stark": {
               "doc_freq": 44,
               "ttf": 47,
               "term_freq": 1,
               "score": 9.272792
            }
         }
      }
   }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Flask 使用 Elasticsearch 进行向量查询,可以借助 Elasticsearch 官方提供的 elasticsearch-dsl 库。 以下是一个简单的示例,展示如何在 Flask 使用 Elasticsearch 进行向量查询: ```python from flask import Flask, request, jsonify from elasticsearch import Elasticsearch from elasticsearch_dsl import Search, Q app = Flask(__name__) es = Elasticsearch() @app.route('/search', methods=['POST']) def search(): # 获取查询向量 query_vector = request.json['vector'] # 构建 Elasticsearch 查询 s = Search(using=es, index='index_name') s = s.query(Q({"script_score": {"query": {"match_all": {}}, "script": {"source": "cosineSimilarity(params.query_vector, 'vector_field')", "params": {"query_vector": query_vector}}}})) # 执行查询 response = s.execute() # 处理查询结果 results = [] for hit in response.hits: results.append({ 'id': hit.meta.id, 'score': hit.meta.score, 'source': hit.to_dict() }) return jsonify(results) ``` 在上面的示例,我们首先从请求获取查询向量,然后使用 Elasticsearch DSL 构建一个 Elasticsearch 查询。这个查询使用脚本评分(`script_score`)来计算查询向量和文档向量之间的余弦相似度(`cosineSimilarity`),然后将得分作为文档的评分。 最后,我们执行查询,将查询结果转换为 JSON 格式,并返回给客户端。 注意,在上面的示例,我们使用了 `request.json` 来获取请求的 JSON 数据。这需要在 Flask 启用 JSON 请求支持,可以使用以下代码实现: ```python from flask import Flask, request app = Flask(__name__) @app.before_request def before_request(): if request.method == 'POST' and request.is_json: request.json = request.get_json() ``` 在上面的示例,我们使用 Flask 的 `before_request` 钩子函数,在每个请求到来之前,检查请求是否是 JSON 请求,如果是,则将请求的 JSON 数据解析为 Python 对象,并将其设置为 `request.json` 属性。这样,在后续的请求处理,我们就可以方便地使用 `request.json` 来获取请求的 JSON 数据了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值