我使用NEST的方法IndexMany(批量索引)遇到了小问题。我发现当我将一些项目发送到elasticsearch进行索引时,会立即返回响应,但此时并非所有文档都被编入索引。
可以在以下代码中轻松显示问题:
List<object> objectToIndex = new List<object>(); // assume 3000 items here
ElasticClient client = new ElasticClient(settings);
client.IndexMany(objectsToIndex, indexName, type);
var readResult = client.Search<T>(e => e
.Type(type)
.Index(indexName)
.Query(q => q
.Range(r => r.OnField(t => t.Date).GreaterOrEquals(dates[0]).LowerOrEquals(dates[1]))
)
);
// read result contains only 300-500 items
System.Threading.Thread.Sleep(2000);
readResult = client.Search<T>(e => e
.Type(type)
.Index(indexName)
.Query(q => q
.Range(r => r.OnField(t => t.Date).GreaterOrEquals(dates[0]).LowerOrEquals(dates[1]))
)
);
// readResult contains all 3000 items right now
这对我来说是个问题,因为我需要批量索引所有文档,然后全部阅读。当然,我可以在批量索引之后运行Thread.Sleep(..),但这对我来说不是解决方案。
Elasticsearch版本为2.2.0,NEST客户端版本为1.7.2。
那么,有没有办法强制弹性/ NEST等到所有文档都被索引后再继续?
答案 0 :(得分:1)
NEST 2.x is not compatible with Elasticsearch 1.x;虽然它可能在大多数情况下都有效,但它在1.x中未经测试,并且Elasticsearch 1.x和2.x之间存在重大变化,这些变化反映在NEST的变化中,例如,服务器错误响应,这将导致运行时的序列化异常。您应该将最新的NEST / Elasticsearch.Net 1.x(currently 1.8.0)与Elasticsearch 1.x一起使用。
此处需要在索引率与允许新索引项目可供搜索之间进行权衡。通过将刷新间隔从1秒更改为更长的时间(例如30秒),或者在索引(-1)时完全禁用它,然后在完成后设置回1秒,您可能会看到更好的索引速率,需要等待索引文档可用于搜索后更长时间。相反,如果索引的项目尽快可用于搜索更为重要,那么您可以通过请求中的刷新调用发送较小的批量批量,例如
client.Bulk(b => b
.CreateMany(objectToIndex, (c, doc) => c
.Document(doc)
.Type(type)
.Index(indexName)
)
.Refresh()
);
需要注意的是,更频繁地调用刷新可能会增加群集的负载,并且索引会花费更长的时间。
如果您必须等到所有文档都被编入索引,我建议对搜索进行计数,以减少需要反序列化的响应的大小
var countResponse = client.Count<MyClass>(c => c
.Type(type)
.Index(indexName)
.Query(q => q
.Range(r => r
.OnField(t => t.Date)
.GreaterOrEquals(dates[0])
.LowerOrEquals(dates[1])
)
)
);
var count = countResponse.Count;
答案 1 :(得分:0)
所以,如果我错了,请纠正我,但我发现它可能与已知问题有关 - https://github.com/elastic/elasticsearch/issues/1063。
无论如何,问题可能因为弹性搜索尚未刷新而发生,所以我更新了我的代码以手动调用Refresh方法然后等待1秒,因为它是默认的自动刷新间隔。
List<object> objectToIndex = new List<object>(); // assume 3000 items here
ElasticClient client = new ElasticClient(settings);
client.IndexMany(objectsToIndex, indexName, type);
// Do the refresh and wait
client.Refresh();
System.Threading.Thread.Sleep(1000);
var readResult = client.Search<T>(e => e
.Type(type)
.Index(indexName)
.Query(q => q
.Range(r => r.OnField(t => t.Date).GreaterOrEquals(dates[0]).LowerOrEquals(dates[1]))
)
);
// readResult SHOULD contain all 3000 files
但这并不能解决问题,因为有时候,当ES处于压力之下时,刷新可能需要1秒以上。
目前,确保所有数据都可搜索的最佳和最安全的方法(就我而言)是在循环中发送搜索请求并等待直到搜索到所需数量的文档。
修改强> Russ Cam在他的回答中对这个问题有了更具体的解释。此外,他建议不要搜索文档,而只是计数以节省一些网络负载。