数据写入与查询

更新时间:
复制 MD 格式

本文介绍如何向PolarDB-X智能搜索(Search引擎)写入数据,以及如何使用全文检索、向量检索(KNN)、混合查询和聚合分析。

数据写入

单条文档写入

# 指定文档 ID 写入
curl -XPUT "https://<Search引擎地址>:9200/products/_doc/1" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '{
    "name":        "无线蓝牙耳机",
    "description": "高品质降噪蓝牙耳机,续航 30 小时",
    "price":       299.0,
    "category":    "电子产品",
    "tags":        ["蓝牙","降噪","耳机"],
    "in_stock":    true,
    "created_at":  "2025-06-01"
  }'

# 自动生成文档 ID
curl -XPOST "https://<Search引擎地址>:9200/products/_doc" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '{ "name": "机械键盘", "price": 499.0, "category": "电子产品" }'

批量写入(_bulk API)

_bulk API 支持在一次请求中执行多个写入操作,显著提高写入效率:

curl -XPOST "https://<Search引擎地址>:9200/_bulk" \
  -u "<用户名>:<密码>" -k \
  -H "Content-Type: application/json" \
  -d '
{"index": {"_index": "products", "_id": "3"}}
{"name": "智能手表", "price": 899.0, "category": "穿戴设备"}
{"index": {"_index": "products", "_id": "4"}}
{"name": "移动电源", "price": 129.0, "category": "电子产品"}
'

批量写入建议

  • 单次 bulk 大小:5-15 MB,避免请求过大导致内存压力。

  • 单次文档数:1000-5000 条,取决于单条文档大小。

  • 并发写入线程:2-4 个,根据节点 CPU 核数调整。

  • 写入期间 refresh_interval 设为 30s 或 -1,写入完成后恢复为 1s。

更新与删除

# 部分更新
curl -XPOST "https://<Search引擎地址>:9200/products/_update/1" \
  -u "<用户名>:<密码>" -k -H "Content-Type: application/json" \
  -d '{ "doc": { "price": 259.0, "in_stock": false } }'

# 删除单条
curl -XDELETE "https://<Search引擎地址>:9200/products/_doc/1" -u "<用户名>:<密码>" -k

# 按查询条件批量删除
curl -XPOST "https://<Search引擎地址>:9200/products/_delete_by_query" \
  -u "<用户名>:<密码>" -k -H "Content-Type: application/json" \
  -d '{ "query": { "term": { "in_stock": false } } }'

全文检索

match 查询

最常用的全文检索查询,会对查询文本进行分词后匹配:

{
  "query": {
    "match": {
      "description": {
        "query": "降噪 蓝牙",
        "operator": "and",
        "minimum_should_match": "75%"
      }
    }
  }
}

multi_match 查询

{
  "query": {
    "multi_match": {
      "query": "智能手表运动",
      "fields": ["name^3", "description"],
      "type": "best_fields"
    }
  }
}
说明

name^3:表示 name 字段的权重是 description 的 3 倍。

match_phrase 短语查询

要求分词后的 token 按顺序紧邻出现:

{ "query": { "match_phrase": { "description": "智能手表" } } }

query_string 查询(Lucene 语法)

{
  "query": {
    "query_string": {
      "query":         "(降噪 OR 蓝牙) AND 耳机",
      "default_field": "description"
    }
  }
}

高亮显示

{
  "query": { "match": { "description": "降噪耳机" } },
  "highlight": {
    "pre_tags":  ["<em>"],
    "post_tags": ["</em>"],
    "fields": {
      "description": {
        "fragment_size":       150,
        "number_of_fragments": 3
      }
    }
  }
}

分页

浅层分页(前 10000 条以内)用 from + size;深度分页用 search_after:

{
  "size": 10,
  "query": { "match_all": {} },
  "sort":  [ { "created_at": "desc" }, { "_id": "asc" } ],
  "search_after": ["2025-05-25", "4"]
}
说明

避免使用 from + size 进行深度分页(如 from=10000),会导致严重的性能问题。推荐使用 search_after

精确查询与过滤

// term
{ "query": { "term":  { "category": "电子产品" } } }

// terms
{ "query": { "terms": { "category": ["电子产品","穿戴设备"] } } }

// range
{ "query": { "range": { "price": { "gte": 100, "lte": 500 } } } }

// 日期范围
{ "query": { "range": { "created_at": { "gte": "2025-05-01", "lt": "2025-06-01" } } } }

// exists
{ "query": { "exists": { "field": "tags" } } }

Bool 复合查询

{
  "query": {
    "bool": {
      "must":     [ { "match": { "description": "耳机" } } ],
      "filter":   [
        { "term":  { "in_stock": true } },
        { "range": { "price": { "lte": 500 } } }
      ],
      "should":   [ { "term": { "tags":     "降噪" } } ],
      "must_not": [ { "term": { "category": "穿戴设备" } } ]
    }
  }
}

子句

说明

是否参与评分

must

必须匹配

filter

必须匹配,但不参与评分

否(利用缓存,性能更好)

should

至少匹配一个可加分

must_not

必须不匹配

说明

不需要评分的过滤条件(如状态、日期范围)放在 filter 中,利用缓存提升性能。

向量检索(KNN)

基本 KNN 查询

{
  "size": 5,
  "query": {
    "knn": {
      "embedding": {
        "vector": [0.1, 0.2, 0.3, "..."],
        "k":      5
      }
    }
  }
}

带过滤条件的向量检索

{
  "size": 5,
  "query": {
    "knn": {
      "embedding": {
        "vector": [0.1, 0.2, 0.3, "..."],
        "k":      5,
        "filter": {
          "bool": {
            "must": [
              { "term":  { "category":   "技术文档" } },
              { "range": { "created_at": { "gte": "2025-01-01" } } }
            ]
          }
        }
      }
    }
  }
}

向量 + 全文混合检索

{
  "size": 10,
  "query": {
    "bool": {
      "should": [
        { "match": { "content":   { "query": "分布式数据库架构", "boost": 0.3 } } },
        { "knn":   { "embedding": { "vector": [0.1, 0.2, 0.3, "..."], "k": 10 } } }
      ]
    }
  }
}

聚合分析

// Metric 聚合
{
  "size": 0,
  "aggs": {
    "avg_price":   { "avg":   { "field": "price" } },
    "max_price":   { "max":   { "field": "price" } },
    "min_price":   { "min":   { "field": "price" } },
    "price_stats": { "stats": { "field": "price" } }
  }
}

// Terms 分组聚合(嵌套子聚合)
{
  "size": 0,
  "aggs": {
    "by_category": {
      "terms": { "field": "category", "size": 10, "order": { "_count": "desc" } },
      "aggs":  { "avg_price": { "avg": { "field": "price" } } }
    }
  }
}

// Date Histogram
{
  "size": 0,
  "aggs": {
    "products_over_time": {
      "date_histogram": { "field": "created_at", "calendar_interval": "month", "format": "yyyy-MM" }
    }
  }
}

地理位置查询

// geo_distance
{
  "query": {
    "geo_distance": {
      "distance": "5km",
      "location": { "lat": 31.23, "lon": 121.47 }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": { "lat": 31.23, "lon": 121.47 },
        "order":    "asc",
        "unit":     "km"
      }
    }
  ]
}

// geo_bounding_box
{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left":     { "lat": 31.3, "lon": 121.4 },
        "bottom_right": { "lat": 31.1, "lon": 121.6 }
      }
    }
  }
}