在2009年,在论文中开始尝试全文本搜索,那时需要为一个数据推荐系统实现一个搜索算法。这次经历非常具有教育意义,但从头开始无疑是一场灾难。当有机会使用库时,尝试了Apache Lucene来实现全文本搜索。随着应用程序架构变得复杂(例如,需要共享索引数据的多个服务器),Solr提供了一个可扩展的解决方案。它是一个基于Lucene的开源API搜索引擎。在使用了这些库之后,使用了Elasticsearch,它现在是市场领导者。它提供免费的本地版本,也可以在云上使用。它可以从简单的安装扩展到巨大的环境。那么,为什么不使用它呢?
在生产环境中成功使用了Elasticsearch,并且在开源无头CMS,RawCMS中也使用了它。为了展示Elasticsearch的工作原理,创建了一个示例应用程序,其中实现了两个主要功能:
示例代码可以在GitHub上找到。要运行和测试它,只需下载、编译并执行:
dotnet ElasticSearchTest.dll create -f divina_commedia.txt -h http://localhost:9300
索引创建在30338毫秒内完成,包含14006个元素。
dotnet ElasticSearchTest.dll search -i divinacommediatxt -h http://localhost:9300 -q "dante AND virgi*"
搜索 "dante AND virgi*"
Dante, perché Virgilio se ne vada,
控制台应用程序使用ConsoleLineParser库以人性化的方式解析输入。只是添加了两个类用于动词属性,以及控制台动词和要运行的代码之间的映射。
private static void Main(string[] args)
{
object x = CommandLine.Parser.Default.ParseArguments<CreateOptions, SearchOptions>(args)
.MapResult(
(CreateOptions opts) => DoCreate(opts),
(SearchOptions opts) => DoSearch(opts),
errs => 1
);
}
根据用户输入的动词(搜索或创建),启动相应的过程并传递参数。
编写部分相当简单。实际上,对于Elasticsearch,有两种选择。使用低级框架,可以直接获得弹性API的包装实现。这有助于避免手动绑定和组合JSON有效载荷。然而,如果想玩转数据,一个好的选择是NEST。NEST是一个高级框架,如果是一个ORM专家,这应该不会让感到惊讶。
只需要为想保存的文档创建类,并使用注释定义如何保存属性,并调用保存API。
public class LogDocument
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Body { get; set; }
}
下一步是创建索引。在这一步中,将索引与类关联起来。这可以手动完成,指定存储设置,或者使用自动映射。在示例中,"Id"字段自动映射到文档的唯一标识符。
client.Indices.Create(indexName, c => c
.Map<LogDocument>(m => m
.AutoMap<LogDocument>()
)
);
最后,有代码中最愚蠢的部分:写入数据。因为想要将所有诗歌的行保存到许多文档中,每行一个文档,只需要一个迭代。
string[] lines = File.ReadAllLines(filepath);
int items = 0;
Parallel.ForEach(lines, (line) =>
{
if (!string.IsNullOrWhiteSpace(line))
{
client.CreateDocument<LogDocument>(
new LogDocument()
{
Body = line.Trim()
});
items++;
}
});
请注意,使用外部系统的API,可以使用并行结构来提高性能。
这部分相当简单且非常清晰——至少希望如此。访问文档的基本方法是使用常规的流畅LINQ语法。这是基本用法,更愿意将这个演示集中在不太为人所知的全文本数据搜索用例上。
Elastic允许使用原始查询在字段数据上进行查找。为此,可以使用Search方法的正确重载,配置原始查询:
var searchResponse = client.Search<LogDocument>(s => s
.Size(10)
.Query(q => q.QueryString(
qs => qs.Query(searchStr)
.AllowLeadingWildcard(true)
))
);
var docs = searchResponse.Documents;
Elasticsearch是领先的搜索引擎解决方案。它为应用程序提供了丰富的功能,如全文本搜索或文档索引。它可以作为服务使用,也可以在本地使用。在任何情况下,它都非常简单,易于配置基本使用。
NEST框架允许像访问简单数据库一样存储和访问Elasticsearch,通过LINQ,这使得一切变得非常简单。
对于复杂的场景,如果想让最终用户编写他们的查询,可以使用原始查询并将结果映射到类。