我有不同类型的文档,这些文档派生自名为Topic的基本类型。我想用:
Client.Bulk(b => b.CreateMany(documents)
只需一次调用Bulk即可处理所有文档,如何设置每个文档的类型?
以下是一段代码:
public IEnumerable<IBulkResponse> CreateBulkTopics(IEnumerable<Topic> topics)
{
var results = new List<IBulkResponse>();
results.Add(IndexDocuments(TopicFactory.ConvertDrugsToDocuments(topics)));
results.Add(IndexDocuments(TopicFactory.ConvertTreatmentSummariesToDocuments(topics)));
return results;
}
public IBulkResponse IndexDocuments(IEnumerable<Common.Elastic.Models.Topic> documents)
{
return ElasticConnector.Client.Bulk(b => b.CreateMany(documents));
}
此时的问题是所有文件都被存储为“主题”,而不是像药物和治疗方法那样的派生类型。
答案 0 :(得分:2)
从Topic
继承了多少种类型?它们是恒定的还是小的?那么类似的东西可以帮助你。让我们说TopicA和TopicB继承自Topic:
public IEnumerable<IBulkResponse> IndexDocuments(IEnumerable<Common.Elastic.Models.Topic> documents)
{
yield return ElasticConnector.Client.Bulk(b => b.CreateMany(documents.OfType<TopicA>()));
yield return ElasticConnector.Client.Bulk(b => b.CreateMany(documents.OfType<TopicB>()));
}
然后在CreateBulkTopics
:
results.AddRange(IndexDocuments(....
当然,只有当子类的数量很小并且可用于此代码时,这才有效。否则,您可以使用反射来实现相同的结果。示例代码有点复杂,但请告诉我您是否需要它。此外,如果子类的数量非常高,这将降低性能,因为它会将单独的请求中的每个类型发送到Bulk api。我认为客户中没有更好的评价。
编辑:这是你用反射做的方法:
class MyClass
{
public IBulkResponse IndexDocuments<T>(IEnumerable<Topic> documents)
where T : Topic
{
var derived = documents.OfType<T>();
return ElasticConnector.Client.Bulk(b => b.CreateMany(derived));
}
public IEnumerable<IBulkResponse> IndexDocumentsByType(IEnumerable<Topic> documents)
{
var groups = documents.GroupBy(x => x.GetType());
var method = typeof(MyClass).GetMethod(nameof(IndexDocuments)); //prior to c#6, typeof(MyClass).GetMethod("IndexDocuments")
foreach (var group in groups)
{
var generic = method.MakeGenericMethod(group.Key);
var result = generic.Invoke(this, new object[] { group });
yield return result as IBulkResponse;
}
}
}
class Program
{
static void Main(string[] args)
{
var documents = new Topic[] { new TopicA(), new TopicA(), new TopicB(), new Topic() };
var result = new MyClass().IndexDocumentsByType(documents);
Console.WriteLine(result.Count()); //writes 3
}
}
答案 1 :(得分:0)
我设法使用泛型类:
public class IndexOperations<T> where T:Topic
{
public ElasticConnector ElasticConnector { get; set; }
public IndexOperations(ElasticConnector elasticConnector)
{
ElasticConnector = elasticConnector;
}
public IBulkResponse CreateMany(IEnumerable<T> t)
{
return ElasticConnector.Client.Bulk(b => b.CreateMany(t));
}
}
客户代码:
var documents = TopicFactory.ConvertToDocuments(topics);
SaveDrugs(documents);
public IBulkResponse SaveDrugs(IEnumerable<Common.Elastic.Models.Topic> documents)
{
var indexOperations = new IndexOperations<Drug>(ElasticConnector);
return indexOperations.CreateMany(documents.OfType<Drug>());
}