Migrating Elasticsearch Vectors to Easysearch: Why Changing Only the Field Name Isn’t Enough

The article explains that while dense vector data can be moved from Elasticsearch to Easysearch, the field types, indexing algorithms, query DSL, and filter semantics differ, requiring careful mapping changes, query rewrites, and thorough validation to avoid mismatched results.

Mingyi World Elasticsearch
Mingyi World Elasticsearch
Mingyi World Elasticsearch
Migrating Elasticsearch Vectors to Easysearch: Why Changing Only the Field Name Isn’t Enough

1. Field type replacements

dense_vector

knn_dense_float_vector – data can be kept (array format compatible). knn_vector (partial ecosystem) → knn_dense_float_vector – data can be kept. sparse_vectorknn_sparse_bool_vector – data shape differs (see section 5).

2. Mapping examples

Original Elasticsearch mapping (dense vector):

PUT /products
{
  "mappings": {
    "properties": {
      "embedding": {
        "type": "dense_vector",
        "dims": 768,
        "index": true,
        "similarity": "cosine",
        "index_options": { "type": "int8_hnsw" }
      }
    }
  }
}

Corresponding Easysearch mapping (Easysearch 2.3.1):

PUT /products
{
  "mappings": {
    "properties": {
      "embedding": {
        "type": "knn_dense_float_vector",
        "knn": {
          "dims": 768,
          "model": "lsh",
          "similarity": "cosine",
          "L": 99,
          "k": 1
        }
      }
    }
  }
}

3. Query DSL adjustments

Elasticsearch 8 typical query:

POST /products/_search
{
  "knn": {
    "field": "embedding",
    "query_vector": [0.12, -0.03, 0.88, 0.45],
    "k": 10,
    "num_candidates": 100,
    "filter": { "term": { "category": "tech" } }
  }
}

Easysearch uses knn_nearest_neighbors and places the vector inside a values array:

POST /products/_search
{
  "size": 10,
  "query": {
    "knn_nearest_neighbors": {
      "field": "embedding",
      "vec": { "values": [0.12, -0.03, 0.88, 0.45] },
      "model": "lsh",
      "similarity": "cosine",
      "candidates": 100
    }
  }
}

For exact search set model": "exact" and omit the candidates parameter.

4. Filter semantics are not equivalent

In Elasticsearch the filter inside knn is a *pre‑filter*: it reduces the candidate set before the nearest‑neighbor search, helping to return a full k of documents that satisfy both similarity and the filter.

Easysearch allows a bool query combined with a filter. This behaves as a *post‑filter*: neighbors are retrieved first, then non‑matching documents are removed. When the filter is selective, the final result set may contain fewer than k items and the ranking can differ from Elasticsearch.

Empirical test on Easysearch 2.3.1 shows that LSH + bool filter does not reproduce Elasticsearch pre‑filter results.

Recommended approaches:

Small data sets that require exact alignment → use model: "exact" together with the bool filter.

Large data sets where approximate recall is acceptable → keep model: "lsh" and increase candidates to improve overlap.

If strict pre‑filter semantics are required, Easysearch currently has no direct equivalent; consider redesigning the query logic.

5. Sparse vector mismatch

Elasticsearch sparse_vector (used with ELSER) is a *weighted* sparse representation: each token carries a weight and similarity incorporates those weights.

Easysearch knn_sparse_bool_vector is a *Boolean* sparse vector: only the indices of true dimensions are stored, and similarity is computed with Jaccard or Hamming.

Example document for a Boolean sparse vector (dimension 1000, true indices 0, 3, 5, 12, 88):

{
  "features": [[0, 3, 5, 12, 88], 1000]
}

Index creation (Easysearch 2.3.1):

PUT /products_0712
{
  "mappings": {
    "properties": {
      "features": {
        "type": "knn_sparse_bool_vector",
        "knn": {
          "dims": 1000,
          "model": "lsh",
          "similarity": "jaccard",
          "L": 99,
          "k": 1
        }
      }
    }
  }
}

Insert a document (format unchanged):

POST /products_0712/_doc/1
{
  "features": [[0, 3, 5, 12, 88], 1000]
}

Query example (LSH‑accelerated):

POST /products_0712/_search
{
  "query": {
    "knn_nearest_neighbors": {
      "field": "features",
      "vec": [[0, 5, 12, 100, 456], 1000],
      "model": "lsh",
      "similarity": "jaccard",
      "candidates": 50
    }
  }
}

Key points:

When defining a knn_sparse_bool_vector, model must be lsh or exact; sparse_indexed is not supported.

The stored format is always [[true‑index‑list], total‑dims].

During query, pass the vector directly (no extra values wrapper) and keep the model consistent with the mapping.

6. Migration decision matrix

Only dense float embeddings → replace field type with knn_dense_float_vector and adjust DSL.

Depend on int8_hnsw for memory‑efficient indexing → Easysearch lacks int8 quantization; choose LSH or exact and re‑benchmark memory vs recall.

Rely on knn pre‑filter consistency → LSH is not equivalent; for small indices use exact + filter, for large indices accept approximation.

Use weighted sparse ( sparse_vector ) → cannot map directly; redesign using Boolean sparse or another approach.

ES 7.12+/8.x snapshot migration → prefer INFINI Gateway migration; build new mapping on the target side before bulk loading.

7. Pre‑release validation checklist (five steps)

Document count (including non‑null vector fields) matches between source and target.

Top‑K overlap without filters between Elasticsearch and Easysearch.

Top‑K overlap with filters – test separately to catch post‑filter differences.

Latency and memory tuning for LSH parameters ( L, k, candidates); do not reuse Elasticsearch num_candidates values.

Core business‑flow load test (recommendation, semantic search, RAG recall) with real traffic replay.

8. Final takeaways

Dense vectors: data compatible, but field type and query DSL must be changed.

Approximate index: replace HNSW/int8 with LSH or exact and retune parameters.

Filter semantics: LSH post‑filter ≠ ES pre‑filter; exact search is closer but still requires verification.

Sparse vectors: Boolean sparse ≠ weighted sparse – they are not interchangeable.

Easysearch 2.3.1 provides its own dense‑float and Boolean‑sparse implementations (exact, LSH, sparse_indexed). Migration therefore concerns semantic equivalence, not merely feature presence.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Migrationelasticsearchvector searchLSHknndense_vectorEasysearchsparse_vector
Mingyi World Elasticsearch
Written by

Mingyi World Elasticsearch

The leading WeChat public account for Elasticsearch fundamentals, advanced topics, and hands‑on practice. Join us to dive deep into the ELK Stack (Elasticsearch, Logstash, Kibana, Beats).

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.