Skip to main content
Version: nightly 🚧

创建搜索应用

现在已经 安装并运行了 kumosearch, 我们准备创建一个 kumosearch 索引表,将一些文档索引进去,并尝试搜索它们。

样本数据集

为了继续进行,点击下载即可获取我们为本开发手册准备的小数据集。

cd /tmp
curl -O https://gitee.com/kumo-ai/kumosearch-datasets/releases/download/v1.0.0/books.jsonl.gz
gunzip books.jsonl.gz

下载后,你将获得一个名为 books.jsonl 的文件,我们将在接下来的步骤中使用它。

初始化客户端

首先,我们需要将 kumosearch 客户端指向 kumosearch 节点进行配置。

/*
* Our JavaScript client library works on both the server and the browser.
* When using the library on the browser, please be sure to use the
* search-only API Key rather than the master API key since the latter
* has write access to kumosearch and you don't want to expose that.
*/

const kumosearch = require('kumosearch')

let client = new kumosearch.Client({
'nodes': [{
'host': 'localhost',
'port': 8808,
'protocol': 'http'
}],
'apiKey': '<API_KEY>',
'connectionTimeoutSeconds': 2
})

我们现在准备开始与 kumosearch 服务器进行交互。

创建 books 索引表

在 kumosearch 中,Collection 索引表 是一组相关的 Document 文档,类似于关系数据库中的表。当我们创建一个索引表时,我们为其指定一个名称,并描述当文档被添加到索引表时应索引的字段。

let booksSchema = {
'name': 'books',
'fields': [
{'name': 'title', 'type': 'string'},
{'name': 'authors', 'type': 'string[]', 'facet': true},

{'name': 'publication_year', 'type': 'int32', 'facet': true},
{'name': 'ratings_count', 'type': 'int32'},
{'name': 'average_rating', 'type': 'float'}
],
'default_sorting_field': 'ratings_count'
}

client.collections().create(booksSchema)
.then(function (data) {
console.log(data)
})

对于每个字段,我们定义它的名称类型以及它是否是facet分面字段。分面字段允许我们将搜索结果聚类为类别,便于深入分析每个类别。

此外,我们还定义了一个default_sorting_field,用于在未提供sort_by子句时确定结果的排序方式。在这种情况下,评分越高的书籍会排名靠前。

索引字段与非索引字段

您只需要在索引表schema中包含那些需要进行 search / filter / facet / sort / group_by 的字段,这些字段被称为索引字段。索引字段存储在 RAM 中,并备份在磁盘上。

将文档导入 kumosearch 时,您仍然可以发送用于显示目的的其他字段(例如:图像 URL)。这些字段在导入文档时如果未在schema中定义,只会存储在磁盘上,并在文档被访问时返回。这些字段被称为非索引字段,有助于节省内存,并避免在构建内存中的未使用索引时浪费 CPU 资源。

将books添加到索引表中

现在,我们准备将一些书籍索引到刚刚创建的索引表中。

    var fs = require('fs/promises');

const booksInJsonl = await fs.readFile("/tmp/books.jsonl");
client.collections('books').documents().import(booksInJsonl);

搜索 books

我们从一个简单的搜索查询开始。让我们搜索 harry potter,并要求 kumosearch 按照评分从高到低的顺序对结果进行排序。

    let searchParameters = {
'q' : 'harry potter',
'query_by' : 'title',
'sort_by' : 'ratings_count:desc'
}

client.collections('books')
.documents()
.search(searchParameters)
.then(function (searchResults) {
console.log(searchResults)
})

响应示例

    {
"facet_counts": [],
"found": 27,
"hits": [
{
"highlights": [
{
"field": "title",
"snippet": "<mark>Harry</mark> <mark>Potter</mark> and the Philosopher's Stone"
}
],
"document": {
"authors": [
"J.K. Rowling", "Mary GrandPré"
],
"average_rating": 4.44,
"id": "2",
"image_url": "https://images.gr-assets.com/books/1474154022m/3.jpg",
"publication_year": 1997,
"ratings_count": 4602479,
"title": "Harry Potter and the Philosopher's Stone"
}
},
...
]
}

除了返回匹配的文档外,kumosearch 还通过highlight 属性突出显示查询词在文档中的位置。

想要最新的《哈利·波特》书籍出现在最前面?没问题,我们可以将sort_by 子句更改为publication_year:desc

语义搜索

除了关键字匹配之外,kumosearch 还支持语义匹配功能。

例如,如果您的数据集中有哈利·波特 一词,而用户搜索著名的男孩巫师,语义搜索会返回包含哈利·波特 的记录,因为它与搜索词在语义上相关。

在开发手册中了解更多语义搜索请点击此处

过滤结果

现在,我们调整查询以仅获取 1998 年之前出版的书籍。为此,我们只需在查询中添加一个filter_by 子句:

let searchParameters = {
'q' : 'harry potter',
'query_by' : 'title',
'filter_by' : 'publication_year:<1998',
'sort_by' : 'publication_year:desc'
}

client.collections('books')
.documents()
.search(searchParameters)
.then(function (searchResults) {
console.log(searchResults)
})

响应示例

{
"facet_counts": [],
"found": 24,
"hits": [
{
"highlights": {
"title": {
"field": "title",
"snippet": "<mark>Harry</mark> <mark>Potter</mark> and the Philosopher's Stone"
}
},
"document": {
"authors": [
"J.K. Rowling", "Mary GrandPré"
],
"average_rating": 4.44,
"id": "2",
"image_url": "https://images.gr-assets.com/books/1474154022m/3.jpg",
"publication_year": 1997,
"ratings_count": 4602479,
"title": "Harry Potter and the Philosopher's Stone"
}
},
...
]
}

分面

让我们按作者字段对搜索结果进行分面,看看它是如何工作的。我们通过这个例子还将展示 kumosearch 如何处理拼写错误。让我们搜索experyment(注意拼写错误!)。

let searchParameters = {
'q' : 'experyment',
'query_by' : 'title',
'facet_by' : 'authors',
'sort_by' : 'average_rating:desc'
}

client.collections('books')
.documents()
.search(searchParameters)
.then(function (searchResults) {
console.log(searchResults)
})

如我们在下面结果中看到的,kumosearch 优雅地处理了拼写错误并正确获取了结果。facet_by 子句还为我们提供了每个作者所写书籍数量的详细分类。

响应示例

{
"facet_counts": [
{
"field_name": "authors",
"counts": [
{
"count": 2,
"value": " Käthe Mazur"
},
{
"count": 2,
"value": "Gretchen Rubin"
},
{
"count": 2,
"value": "James Patterson"
},
{
"count": 2,
"value": "Mahatma Gandhi"
}
]
}
],
"found": 3,
"hits": [
{
"_highlight": {
"title": "The Angel <mark>Experiment</mark>"
},
"document": {
"authors": [
"James Patterson"
],
"average_rating": 4.08,
"id": "569",
"image_url": "https://images.gr-assets.com/books/1339277875m/13152.jpg",
"publication_year": 2005,
"ratings_count": 172302,
"title": "The Angel Experiment"
}
},
...
]
}

我们的小演练到这里就结束了。要了解更多关于 kumosearch 的信息,请参阅我们的 链接[API 文档](../../api / README.md)

tip

我们在本例中使用了单个节点,但 kumosearch 也可以在集群模式下运行。有关更多详细信息,请参阅[高可用集群](./high-availability.mdx) 部分。