我想将文档移动到新的 id
,以便它在文档 API 中的另一个 url
上可用。有两种方法可以做到这一点:
1
- 删除旧id的文档
- 用新的id创建文档
2
- 用新的id创建文档
- 删除旧id的文档
方法 1 可能会导致文档不会在搜索中返回。方法 2 可能会导致文档在搜索中多次返回。
有什么办法可以解决吗?
最佳答案
当您创建(索引)或删除文档时,这只会在索引刷新后反射(reflect)在搜索中。所以在实践中你的两种方法都有相同的结果: 直到索引刷新
- 旧文档将在搜索中返回,但使用文档 API (GET/indexname/type/id) 将不可用
- 新文档将通过文档 API 提供,但不会出现在搜索中。
当您快速连续执行索引和删除操作时,甚至可能在单个批量请求中,操作的顺序并不重要。默认情况下,刷新间隔为一秒,因此差异将一直保持到该时间。您可以通过在索引上发出刷新命令来立即强制刷新:
curl -XPOST http://127.0.0.1:9200/testidx/_refresh
在下面的最后一节中提供了事件顺序的说明。
通过添加 URL 参数 refresh=true
,也可以在批量请求后强制刷新。因此,如果您确实需要更改文档的 ID,我会按如下方式进行:
- 可选择禁用自动索引刷新
- 向
- 创建新文档
- 删除旧文档
- 刷新索引
- 重新启用自动索引刷新(如果在 1. 中禁用)
例子:
将文档从 ID 77 移动到 ID 99:
curl -XPOST localhost:9200/testidx/foo/_bulk?refresh=true --data-binary @bulk.json
文件 bulk.json
包含类似的内容
{"index": {"_id": "123"}}
{ ... old document source ... }
{"delete": {"_id": "99"}}
但是,您真的需要更改 ID,还是可以围绕该要求进行工程设计?也许不要以这种方式使用文档 API,而是在每个文档中包含例如 "path"
字段,并基于此(基于搜索 API)制作 URL 方案。然后,您可以通过使用新的 "path"
字段更新文档来移动(更改 URL 路径)文档。
搜索索引刷新示意图
首先添加 doc 77 并在搜索中看到它:
+ curl -XPUT 'http://127.0.0.1:9200/testidx/foo/77' -d '{"boo": "baa"}'
{
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"_version" : 1,
"created" : true
}
+ curl -XPOST http://127.0.0.1:9200/testidx/_refresh
{"_shards":{"total":10,"successful":5,"failed":0}}
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/_search'
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"_score" : 1.0,
"_source":{"boo": "baa"}
} ]
}
}
+ curl -XPUT 'http://127.0.0.1:9200/testidx/_settings' -d '{"settings": { "index.refresh_interval": "-1"}}'
{
"acknowledged" : true
}
然后添加一个新的doc 99:
+ curl -XPUT 'http://127.0.0.1:9200/testidx/foo/99' -d '{"boo": "baa"}'
{
"_index" : "testidx",
"_type" : "foo",
"_id" : "99",
"_version" : 1,
"created" : true
}
99 还没有出现在搜索中:
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/_search'
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"_score" : 1.0,
"_source":{"boo": "baa"}
} ]
}
}
...但是在文档 API 中:
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/99'
{
"_index" : "testidx",
"_type" : "foo",
"_id" : "99",
"_version" : 1,
"found" : true,
"_source":{"boo": "baa"}
}
删除77后,搜索仍然显示77(但不是99):
+ curl -XDELETE 'http://127.0.0.1:9200/testidx/foo/77'
{
"found" : true,
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"_version" : 2
}
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/_search'
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"_score" : 1.0,
"_source":{"boo": "baa"}
} ]
}
但是文档API已经没有77了:
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/77'
{
"_index" : "testidx",
"_type" : "foo",
"_id" : "77",
"found" : false
}
但刷新后,搜索结果反射(reflect)的是当前内容:
+ curl -XPOST http://127.0.0.1:9200/testidx/_refresh
{"_shards":{"total":10,"successful":5,"failed":0}}
+ curl -XGET 'http://127.0.0.1:9200/testidx/foo/_search'
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : "testidx",
"_type" : "foo",
"_id" : "99",
"_score" : 1.0,
"_source":{"boo": "baa"}
} ]
}
}
关于elasticsearch - 如何将文档移动到不同的 ID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25483668/