yari 搜索功能

yari 搜索功能

MDN 的 yari 使用了 Elasticsearch 和 Kibana 来实现搜索功能。 Elasticsearch 是一个开源的搜索引擎,它提供了分布式、多租户、全文搜索和分析等功能。在 MD...

更新于 2023-04-11
2996

MDN 的 yari 使用了 Elasticsearch 和 Kibana 来实现搜索功能。

Elasticsearch 是一个开源的搜索引擎,它提供了分布式、多租户、全文搜索和分析等功能。在 MDN 的 yari 中,Elasticsearch 负责存储和搜索文档内容,并提供高效的搜索结果返回。

Kibana 是一个可视化的数据分析和展示工具,它可以与 Elasticsearch 配合使用,通过图表、表格等形式展示 Elasticsearch 中存储的数据。在 MDN 的 yari 中,Kibana 提供了搜索结果的可视化界面。

具体来说,yari 的搜索功能主要包含以下几个步骤:

  1. 收集数据:yari 会从 MDN 的数据库中获取文档内容、标签等信息,并利用 Elasticsearch API 将这些数据存储至 Elasticsearch 中。

  2. 索引文档:在存储数据时,yari 会将文档内容分析成词条,并根据一定的算法建立索引,以便后续搜索。例如,yari 会将 HTML 标签、JavaScript 函数等词条索引到不同的字段中,并设置不同的权重和搜索规则。

  3. 搜索查询:yari 会根据用户的查询请求,利用 Elasticsearch 提供的搜索 API 在索引中进行检索。搜索算法会根据查询语法、词条、权重等因素进行排名,以获得尽可能精确的搜索结果。当搜索结果超过某个阈值时,yari 会利用 Kibana 将结果可视化展示。

  4. 展示结果:yari 会将搜索结果展示在搜索页面中,并提供一些筛选和排序等功能以帮助用户更准确地找到所需信息。

总的来说,yari 的搜索功能借助了 Elasticsearch 和 Kibana 提供的高效、全面的搜索和分析能力,可以为用户提供快速、准确的搜索结果。

我参考的资料主要有以下几个来源:

  1. 官方文档:我阅读了 Elasticsearch 和 Kibana 的官方文档,了解了它们的基本概念、使用方法、API等内容。

  2. MDN yari 的代码:我分析了 MDN yari 的源代码,特别是搜索模块的代码,了解了它们是如何使用 Elasticsearch 和 Kibana 实现搜索功能的。

  3. 技术文章:我阅读了一些关于 Elasticsearch 和 Kibana 的技术文章,例如《Elasticsearch 权威指南》、《Kibana 实战》等,了解了它们的一些高级用法和最佳实践。

  4. 互联网资料:我查找了一些互联网上的资料,例如博客文章、Stack Overflow 问答等,了解了 Elasticsearch 和 Kibana 在实际应用中的一些问题和解决方法。

MDN 的 yari 使用 ElasticSearch 实现搜索功能。具体实现如下:

  1. 应用中使用了 ElasticSearch 的 JavaScript API client,该客户端提供了操作 ElasticSearch 的方法。

  2. 在应用的服务端代码中,先定义了一个 ElasticSearch 的客户端实例,然后定义了一个搜索函数,在该函数中使用客户端的 search() 方法来实现搜索操作。search() 方法接受一个包含查询条件的 JavaScript 对象作为参数,返回一个 Promise,该 Promise 解析出来的结果是一个 JSON 对象,其中包含搜索到的文档信息。

以下是服务端代码的示例:

js
const { Client } = require('@elastic/elasticsearch');
const client = new Client({ node: 'http://localhost:9200' });
async function search(query) {
return await client.search({
index: 'mdn',
body: {
query: {
multi_match: {
query: query,
fields: ['title^3', 'tags^2', 'summary', 'content']
}
},
highlight: {
fields: {
content: {}
}
}
}
});
}

上述代码中,我们使用了 ElasticSearch 的 multi_match 查询。这个查询会在多个字段中搜索指定的搜索关键字,并按照指定的权重进行计算,最终返回一个包含匹配度的分数,分数越高,表示该匹配越相关。在这里,我们赋予了标题字段 title 更高的权重,标签字段 tags 次之,其余字段的权重相同。

为了让搜索结果更加人性化,我们还进行了高亮处理。在查询结果中,会将匹配到的关键字标记为带有样式的 HTML 标签,以突出显示搜索结果。

  1. 在前端代码中,我们使用了 ElasticLunr.js 作为客户端搜索库,该库提供了类似 ElasticSearch 的查询能力,并支持对搜索结果进行分页、高亮等操作。

以下是客户端代码的示例:

js
const index = elasticlunr(function() {
this.addField('title');
this.addField('tags');
this.addField('summary');
this.addField('content');
});
async function loadData() {
const response = await fetch('/data/mdn.json');
const data = await response.json();
for (const item of data) {
index.addDoc(item);
}
}
function search(query) {
const results = index.search(query, {
fields: {
title: { boost: 3 },
tags: { boost: 2 },
summary: {},
content: {}
},
bool: 'OR',
expand: true,
wildcard: elasticlunr.Query.wildcard.LEADING | elasticlunr.Query.wildcard.TRAILING
});
return results.map(result => ({
...result.doc,
score: result.score
}));
}

上述代码中,我们在客户端中定义了一个 ElasticLunr 的索引,并为不同的字段分配了权重。这里和服务端的 multi_match 查询类似,区别在于 ElasticLunr 不支持在同一字段中指定不同权重,而是需要为每个字段单独指定权重。

在搜索过程中,我们调用了索引实例的 search() 方法,并传入查询字符串和一些其他参数。其中,fields 参数指定了每个字段的权重;bool 参数指定了多个关键字之间的逻辑关系(是 AND 还是 OR);expand 参数指定了是否自动扩展查询字符串(例如将用户输入的 JS 扩展为 JavaScript);wildcard 参数则指定了是否允许使用通配符查询。

具体实现细节可以参考以下资料: