Elasticsearch全文本搜索的实践应用

在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,这使得一切变得非常简单。

对于复杂的场景,如果想让最终用户编写他们的查询,可以使用原始查询并将结果映射到类。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485