创建搜索应用
现在已经 安装并运行了 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 节点进行配置。
- 请确保使用与之前安装 kumosearch 服务器 时相同的 API 密钥。
- JavaScript
- Python
- Shell
/*
* 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
})
import kumosearch
client = kumosearch.Client({
'nodes': [{
'host': 'localhost',
'port': '8868',
'protocol': 'http'
}],
'api_key': '<API_KEY>',
'connection_timeout_seconds': 2
})
export KUMOSEARCH_API_KEY='<API_KEY>'
export KUMOSEARCH_HOST='http://localhost:8868'
我们现在准备开始与 kumosearch 服务器进行交互。
创建 books 索引表
在 kumosearch 中,Collection 索引表 是一组相关的 Document 文档,类似于关系数据库中的表。当我们创建一个索引表时,我们为其指定一个名称,并描述当文档被添加到索引表时应索引的字段。
- JavaScript
- Python
- Shell
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)
})
import kumosearch
books_schema = {
'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(books_schema)
curl "${KUMOSEARCH_HOST}/collections" \
-X POST \
-H "Content-Type: application/json" \
-H "X-KUMOSEARCH-API-KEY: ${KUMOSEARCH_API_KEY}" -d '{
"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"
}'
对于每个字段,我们定义它的名称、类型以及它是否是facet分面字段。分面字段允许我们将搜索结果聚类为类别,便于深入分析每个类别。
此外,我们还定义了一个default_sorting_field,用于在未提供sort_by子句时确定结果的排序方式。在这种情况下,评分越高的书籍会排名靠前。
您只需要在索引表schema中包含那些需要进行 search / filter / facet / sort / group_by 的字段,这些字段被称为索引字段。索引字段存储在 RAM 中,并备份在磁盘上。
将文档导入 kumosearch 时,您仍然可以发送用于显示目的的其他字段(例如:图像 URL)。这些字段在导入文档时如果未在schema中定义,只会存储在磁盘上,并在文档被访问时返回。这些字段被称为非索引字段,有助于节省内存,并避免在构建内存中的未使用索引时浪费 CPU 资源。
将books添加到索引表中
现在,我们准备将一些书籍索引到刚刚创建的索引表中。
- JavaScript
- Python
- shell
var fs = require('fs/promises');
const booksInJsonl = await fs.readFile("/tmp/books.jsonl");
client.collections('books').documents().import(booksInJsonl);
with open('/tmp/books.jsonl') as jsonl_file:
client.collections['books'].documents.import_(jsonl_file.read().encode('utf-8'))
curl "${KUMOSEARCH_HOST}/collections/books/documents/import" \
-X POST \
-H "X-KUMOSEARCH-API-KEY: ${KUMOSEARCH_API_KEY}" \
--data-binary @/tmp/books.jsonl
搜索 books
我们从一个简单的搜索查询开始。让我们搜索 harry potter,并要求 kumosearch 按照评分从高到低的顺序对结果进行排序。
- JavaScript
- Python
- shell
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)
})
search_parameters = {
'q' : 'harry potter',
'query_by' : 'title',
'sort_by' : 'ratings_count:desc'
}
client.collections['books'].documents.search(search_parameters)
curl -H "X-KUMOSEARCH-API-KEY: ${KUMOSEARCH_API_KEY}" \
"${KUMOSEARCH_HOST}/collections/books/documents/search\
?q=harry+potter&query_by=title&sort_by=ratings_count:desc"
响应示例
- JSON
{
"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 子句:
- JavaScript
- Python
- Shell
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)
})
search_parameters = {
'q' : 'harry potter',
'query_by' : 'title',
'filter_by' : 'publication_year:<1998',
'sort_by' : 'publication_year:desc'
}
client.collections['books'].documents.search(search_parameters)
curl -H "X-KUMOSEARCH-API-KEY: ${KUMOSEARCH_API_KEY}" \
"${KUMOSEARCH_HOST}/collections/books/documents/search\
?q=harry+potter&query_by=title&sort_by=publication_year:desc\
&filter_by=publication_year:
<
1998"
响应示例
- JSON
{
"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(注意拼写错误!)。
- JavaScript
- Python
- Shell
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)
})
search_parameters = {
'q' : 'experyment',
'query_by' : 'title',
'facet_by' : 'authors',
'sort_by' : 'average_rating:desc'
}
client.collections['books'].documents.search(search_parameters)
curl -H "X-KUMOSEARCH-API-KEY: ${KUMOSEARCH_API_KEY}" \
"${KUMOSEARCH_HOST}/collections/books/documents/search\
?q=experyment&query_by=title&sort_by=average_rating:desc\
&facet_by=authors"
如我们在下面结果中看到的,kumosearch 优雅地处理了拼写错误并正确获取了结果。facet_by 子句还为我们提供了每个作者所写书籍数量的详细分类。
响应示例
- JSON
{
"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)。
我们在本例中使用了单个节点,但 kumosearch 也可以在集群模式下运行。有关更多详细信息,请参阅[高可用集群](./high-availability.mdx) 部分。