NEST的方法IndexMany同步运行

时间:2016-05-09 11:57:33

标签: c# elasticsearch nest

我使用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等到所有文档都被索引后再继续?

2 个答案:

答案 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在他的回答中对这个问题有了更具体的解释。此外,他建议不要搜索文档,而只是计数以节省一些网络负载。