为什么选择ElasticsearchCRUD
我想要一个简单的方法来将我的应用程序实体添加,更新或删除到Elasticsearch文档中。 单个上下文可以与许多实体类型一起使用,并且可以根据需要进行非常容易的调整,例如对于所有属性进行小写处理,或者可以定义任何特定的映射。 ElasticLINQ目前没有提供CRUD操作,虽然您可以使用NEST几乎满足任何要求(我也认为它是一个很棒的API),但我发现它有点太复杂了。
设置基本的CRUD实体到文档
创建将在Elasticsearch中保存为文档的实体类:
public class Skill
{
public long Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTimeOffset Created { get; set; }
public DateTimeOffset Updated { get; set; }
}
创建您的ElasticsearchContext和IElasticsearchMappingResolver。 上下文需要Elasticsearch URL。 在映射文件中定义索引以及类型和属性映射
IElasticsearchMappingResolver elasticsearchMappingResolver = new ElasticsearchMappingResolver();
现在我们可以向Elasticsearch添加一些文档
IElasticsearchMappingResolver elasticsearchMappingResolver = new ElasticsearchMappingResolver();
using (var elasticsearchContext = new ElasticsearchContext("http://localhost:9200/", elasticsearchMappingResolver))
{
//为控制台添加一些跟踪
elasticsearchContext.TraceProvider = new ConsoleTraceProvider();
//创建一些文档
elasticsearchContext.AddUpdateDocument(TestData.SkillEf, TestData.SkillEf.Id);
elasticsearchContext.AddUpdateDocument(TestData.SkillOrm, TestData.SkillOrm.Id);
elasticsearchContext.AddUpdateDocument(TestData.SkillSQLServer, TestData.SkillSQLServer.Id);
elasticsearchContext.AddUpdateDocument(TestData.SkillGermanWithFunnyLetters, TestData.SkillGermanWithFunnyLetters.Id);
elasticsearchContext.AddUpdateDocument(TestData.SkillLevel, TestData.SkillLevel.Id);
var addEntitiesResult = elasticsearchContext.SaveChanges();
Console.WriteLine(addEntitiesResult.PayloadResult);
Console.WriteLine(addEntitiesResult.Status);
Console.WriteLine(addEntitiesResult.Description);
}
以下是你如何选择,更新或删除文档
using (var elasticsearchContext = new ElasticsearchContext("http://localhost:9200/", elasticsearchMappingResolver))
{
// 为控制台添加一些跟踪
elasticsearchContext.TraceProvider = new ConsoleTraceProvider();
// 获取一个实体并对其进行更新,然后删除一个实体
Skill singleEntityWithId = elasticsearchContext.GetEntity<Skill>("14");
// 创建一些文档
singleEntityWithId.Updated = DateTime.UtcNow;
elasticsearchContext.AddUpdateDocument(TestData.SkillOrm, TestData.SkillOrm.Id);
// 删除文档
elasticsearchContext.DeleteDocument<Skill>("11");
elasticsearchContext.AddUpdateDocument(TestData.SkillEf, TestData.SkillEf.Id);
var nextResult = elasticsearchContext.SaveChanges();
Console.WriteLine(nextResult.PayloadResult);
Console.WriteLine(nextResult.Status);
Console.WriteLine(nextResult.Description);
}
结果如下:
删除Elasticsearch索引
您也可以从Elasticsearch中删除任何索引。 要删除索引,必须将AllowDeleteForIndex
属性设置为true
。 我添加了这个,因此索引不会默认设置被删除。 通常,您不需要删除索引。
IElasticsearchMappingResolver _elasticsearchMappingResolver = new ElasticsearchMappingResolver();
using (var context = new ElasticsearchContext("http://localhost:9200/", _elasticsearchMappingResolver))
{
context.AllowDeleteForIndex = true;
var entityResult = context.DeleteIndex<SkillTestEntityNoIndex>();
entityResult.Wait();
}
如果您需要特殊的实体/文档映射怎么办?
您可以实现ElasticsearchSerializerMapping,并根据需要定义映射。 以下示例仅使用小写字符映射文档。
public class SkillElasticsearchMapping : ElasticsearchMapping
{
/// <summary>
/// Only required if you have some special mapping or want to remove some properties or use attributes..
/// </summary>
/// <param name="entity"></param>
public override void MapEntityValues(object entity, ElasticsearchCrudJsonWriter elasticsearchCrudJsonWriter, bool beginMappingTree = false)
{
Skill skillEntity = entity as Skill;
MapValue("id", skillEntity.Id, elasticsearchCrudJsonWriter.JsonWriter);
MapValue("name", skillEntity.Name, elasticsearchCrudJsonWriter.JsonWriter);
MapValue("description", skillEntity.Description, elasticsearchCrudJsonWriter.JsonWriter);
MapValue("created", skillEntity.Created.UtcDateTime, elasticsearchCrudJsonWriter.JsonWriter);
MapValue("updated", skillEntity.Updated.UtcDateTime, elasticsearchCrudJsonWriter.JsonWriter);
}
/// <summary>
/// Use this if you require special mapping for the Elasticsearch document type. For example you could pluralize your Type or set everything to lowercase
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public override string GetDocumentType(Type type)
{
return "cooltype";
}
/// <summary>
/// Use this if the index is named differently to the default type.Name.ToLower
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public override string GetIndexForType(Type type)
{
return "skills";
}
}
您可以将其添加到IElasticsearchMappingResolver实现中:
IElasticsearchMappingResolver elasticsearchMappingResolver = new ElasticsearchMappingResolver();
// You only require a mapping if the default settings are not good enough
elasticsearchMappingResolver.AddElasticSearchMappingForEntityType(typeof(Skill), new SkillElasticsearchMapping());
var elasticsearchContext = new ElasticsearchContext("http://localhost:9200/", elasticsearchMappingResolver);
您还可以映射这样的属性:
/// <summary>
/// Here you can do any type of entity mapping
/// </summary>
///
public override void MapEntityValues(object entity, ElasticsearchCrudJsonWriter elasticsearchCrudJsonWriter, bool beginMappingTree = false)
{
var propertyInfo = entity.GetType().GetProperties();
foreach (var prop in propertyInfo)
{
MapValue(prop.Name, prop.GetValue(entity), elasticsearchCrudJsonWriter.JsonWriter);
}
}
跟踪:
您还可以使用您最喜欢的记录器跟踪请求,响应。 所有您需要做的是实现ITraceProvider并在上下文中设置TraceProvider属性。
elasticsearchContext.TraceProvider = new ConsoleTraceProvider();
或者您可以使用System.Diagnostics进行跟踪:
elasticsearchContext.TraceProvider = new TraceProvider("tracingExample");
这是System.Diagnostics配置的一个例子:
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="tracingExample"
switchName="tracingSwitch"
switchType="System.Diagnostics.SourceSwitch" >
<listeners>
<clear/>
<add name="textwriterListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="application.log"
traceOutputOptions="ProcessId, DateTime, Callstack" />
</listeners>
</source>
</sources>
<switches>
<add name="tracingSwitch" value="Verbose" />
</switches>
</system.diagnostics>
ITraceProvider的实现示例:
public class ConsoleTraceProvider : ITraceProvider
{
public void Trace(TraceEventType level, string message, params object[] args)
{
SetForegroundColor(level);
Console.WriteLine(level + ": " + message, args);
}
public void Trace(TraceEventType level, Exception ex, string message, params object[] args)
{
SetForegroundColor(level);
Console.WriteLine(level + ": " + ex.Message + ex.InnerException + message, args);
}
private void SetForegroundColor(TraceEventType level)
{
switch (level)
{
case TraceEventType.Critical:
{
Console.ForegroundColor = ConsoleColor.Red;
break;
}
case TraceEventType.Error:
{
Console.ForegroundColor = ConsoleColor.Magenta;
break;
}
case TraceEventType.Warning:
{
Console.ForegroundColor = ConsoleColor.Yellow;
break;
}
case TraceEventType.Verbose:
{
Console.ForegroundColor = ConsoleColor.Gray;
break;
}
default:
{
Console.ForegroundColor = ConsoleColor.White;
break;
}
}
}
}