在elasticsearch中使用自定义路由进行搜索

polhcujo  于 2023-05-16  发布在  ElasticSearch
关注(0)|答案(1)|浏览(166)

根据elasticsearch文档,下面的搜索请求应该只在包含user1路由值的分片上执行。
查询:

GET my-index-000001/_search?routing=user1
{
  "query": {
    "match": {
      "title": "document"
    }
  }
}

但是,我得到了上面查询的以下结果:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.11859183,
    "hits": [
      {
        "_index": "my-index-000001",
        "_id": "1",
        "_score": 0.11859183,
        "_routing": "user1",
        "_source": {
          "title": "This is a document"
        }
      },
      {
        "_index": "my-index-000001",
        "_id": "2",
        "_score": 0.10943023,
        "_routing": "user1",
        "_source": {
          "title": "This is another new document"
        }
      },
      {
        "_index": "my-index-000001",
        "_id": "3",
        "_score": 0.10158265,
        "_routing": "user2",
        "_source": {
          "title": "This is a document in user2"
        }
      },
      {
        "_index": "my-index-000001",
        "_id": "4",
        "_score": 0.0947853,
        "_routing": "user2",
        "_source": {
          "title": "This is a another document in user2"
        }
      }
    ]
  }
}

尽管在搜索查询中将路由参数指定为user1,但为什么它还检索路由值为user2的文档呢?
是否因为user1和user2都可以驻留在同一个分片上,所以这个查询匹配并检索来自同一个(并且只有一个)分片的所有文档?
我期望得到包含路由值为user1的文档的命中率,但也得到了值为user2的文档的命中率

u0njafvf

u0njafvf1#

当指定路由值时,将只搜索一个分片,如响应中所示。

"_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },

当指定routing=user1时,你不能期望只获得具有user1值的文档,否则这将意味着你有与不同用户值的数量一样多的主分片,这只有在用户数量较低(<10)时才有意义。
路由值不是在搜索查询中过滤数据的一种方法,因为你需要使用term过滤器,它只是一种指定要搜索的特定分片的方法,因为你知道你需要搜索的文档将在那个分片上,因为它们都是用相同的路由值索引的。
最后,如果你的索引只有一个主分片,那么使用路由值不会带来任何好处,因为所有的数据都将在这个单一的分片上被索引。

更新:

以下是对您的评论的回复:
然而,主分片的数量等于不同用户值的数量,即2。因此,为什么两个具有不同路由值的文档被放置在同一个分片上?
使用两个不同的路由值并不意味着它们最终会出现在两个不同的分片中。使用murmur 3散列函数(x86,32位)对路由值进行散列,然后在以下公式中使用以推导分片ID:

shard_num = (hash(_routing) % num_routing_shards) / routing_factor
where routing_factor = num_routing_shards / num_primary_shards

routing_factor是1(即2个路由分片/ 2个主分片),因此分片ID基本上是_routing值mod 2的散列。
使用您的路由值,我们得到以下分片ID(您可以实验murmur 3 here):

murmur3("user1") % 2 = 3305849917 % 2 = shard 1
murmur3("user2") % 2 = 4180509323 % 2 = shard 1

你可以用一个以user3作为路由值的文档进行测试,你会看到它会落在另一个分片上:

murmur3("user3") % 2 = 2032664284 % 2 = shard 0

相关问题