⚠️ 此页面为自动翻译,翻译可能不完美。
blog-post

Mike learning: REPLACE, UPDATE, wordforms

关于我

Mike

大家好,我是Mike。

我最近开始在Manticore担任开发者倡导者。我不是完全远离IT的人,但正在追赶现代技术。在这篇博客中,我将分享我的经验和关于Manticore的学习内容。我计划以日记的形式记录我的旅程,解释Manticore是什么以及如何使用它。让我们一起发现事物如何协同工作,识别问题,并实时与开发者互动。

这是我的第二篇博客文章。如果您有兴趣与我一起学习Manticore,我会在以下地方更新:

第二步:REPLACE,UPDATE,词形

当我撰写 第一篇文章 时,来自宠物店的朋友联系了我。他们想将数据库用于他们的商店,而由于他们的销售员仍然对牵引绳和胸背带感到困惑,我想实现数据库的附加功能。

本文是 上一篇文章 的延续,并基于它。

与大多数数据库不同,Manticore使用先进的模型来识别其存储的文本。文本处理系统基于NLP(自然语言处理)解决方案。

在此处,对技术的一点描述有助于一般理解。NLP旨在识别我们交流的“自然”语言。乍看之下,文本识别似乎没有复杂之处,但随着使用机器学习算法的文本处理解决方案的出现,技术上已经变得如此。在我们的情况下,我们不会深入探讨,而是使用Manticore Search内置的现成文本处理解决方案。该系统使用分词(将文本分成小的独立部分):按句子和单个单词进行分词,这使您能够快速在数据库中找到所需的单词、短语和段落。(有关数据分词的更多信息,请查看此 链接。

关于Manticore利用的技术,有几点说明:

  • 词干提取是将单词减少到其词根形式的过程。例如,“walking”、“walks”和“walked”都是单词“walk”的词干。
  • 词形还原是将单词的不同形式还原为其基本形式(称为词形)的过程。例如,单词“eat”可以以“eating”、“eats”和“ate”的形式出现。所有这些变体的词形都是“eat”,即其基本词典形式。
  • 为了提高高级搜索的准确性和质量,还有其他几种解决方案参与其中:词形、例外词和停用词。

词形还原器和词干提取器执行一个共同的功能,即以不同的方式将单词归一化为相同的形式,每种方式都有其优缺点。

此外,包含常用词列表的停用词文件,如冠词、连词和感叹词,有助于加快处理速度。基本上,所有这些小词使我们的语言听起来不错,但对计算机来说意义不大。

如果标准功能集不足以舒适地操作搜索引擎,例如当数据库包含专业术语或地方俚语,并且词语之间存在具有附加语义意义的逻辑联系时,可以使用附加词形文件。数据库管理员可以在文件中添加词语之间的链接,这些词语在定义规则上有所不同,但在上下文中相似。例如,牵引绳和胸背带。在不同的上下文中,这两个词可能具有相同的意义或完全不同。

在表中使用词形文件

新表

宠物店的朋友们提到他们的销售员对牵引绳和胸背带了解不多。他们建议在查询牵引绳时,也应考虑询问胸背带,反之亦然。

由于牵引绳和胸背带属于同一产品类别,而数据库中没有特定字段来指示它们的组别,因此使用词形文件会很有帮助。该文件可以通过在搜索“牵引绳”时添加相关词汇来帮助。例如,通过将“胸背带”或“flexi”添加到词形字典中,搜索“牵引绳”时也会显示“胸背带”和“flexi”的结果。

让我们看一下这家宠物店提供的产品:

标题描述价格可用性
网眼牵引绳,绿色,最多50公斤,5米坚固的网眼狗牵引绳,适合大型犬品种5.00€
弹性牵引绳,粉色,最多10公斤,3米为优雅女士和她们的四足伴侣准备的美丽牵引绳12.00€
粉色胸背带,最多10公斤用于被释放到街道上并被错误称为狗的看门犬 8.00€
The flexi可伸缩狗牵引绳,10公斤,5米适用于最多10公斤的狗的flexi。长度为5米,考虑到主人拉出手臂的长度7.50€
狗粮,1公斤你宠物的干粮4.30€
猫粮,1公斤如果你的猫大声叫嚷并要求食物! 2.80€
猫用驱蚤项圈猫不应该携带跳蚤。23.20€
狗用驱蚤滴剂,最多10公斤从不速之客身上滴在你的守护者皮肤上的药剂14.30€

我们将使 标题 字段仅作为字符串,使用 描述 进行全文搜索,将 价格 设为浮点数,将 可用性 设为布尔值。

为了在 "牵引绳"、"胸背带" 和 "flexi" 之间建立逻辑词关联,我们将它们放在 /tmp/wordforms/ 文件夹中,并确保该文件在系统所有用户之间共享。

mkdir /tmp/wordforms
cd /tmp/wordforms
mcedit wf_pet_products.txt

MC 内置的编辑器称为 mcedit。要执行它,请输入 mcedit <文件名>

让我们在其中添加我们的词形文件:

flexi > leash
harness > leash

如果你正确执行了所有步骤,你的终端中将显示如下内容:
终端视图
F2 保存
Enter 确认
F10 退出

现在我们有了一个将稍后与新表一起使用的词形文件。请记住或记下它保存的位置:

/tmp/wordforms/wf_pet_products.txt

现在,为了对数据库进行更多更改,我们必须连接到它并设置一个带有我们列的表。然后,我们需要链接一个词干提取器和我们之前创建的词形文件:

mysql -h0 -P9306
CREATE TABLE products (name STRING, info TEXT, price FLOAT, avl BOOL) morphology = 'stem_en' wordforms='/tmp/wordforms/wf_pet_products.txt';

现在让我们检查我们的表中创建了哪些字段:

DESC products;

DESC 结果

我们指定的所有字段都存在,但出现了一个额外的字段 - id。此字段旨在让 Manticore 唯一标识数据库中的文档,因此在表初始化时会自动创建,无论是否指定。info 字段具有 indexed stored 属性,表明其参与全文搜索过程。需要注意的是,字段的顺序与创建表时指定的顺序不同。因此,在填充表时必须考虑这一点,尤其是在不指定字段顺序的情况下更新整个行时。例如,我们稍后将讨论的 REPLACE 命令。

接下来,我们应该验证表的一般参数,例如词形文件和之前连接的词干提取器。创建表时,如果词形文件名有错误,系统将忽略它,不会产生任何错误或警告。

SHOW TABLE products SETTINGS;

显示表 products 设置结果

上面你可以注意到,尽管我们在 /tmp/wordforms/ 中指定了文件路径,但 Manticore 将其保存在 /var/lib/manticore/products/ 中。这表明 Manticore 已将文件的副本附加到创建的表中。现在该文件已固定用于索引此表。出于设计原因,无法实时替换词形文件,因为这需要重新索引整个表,如果你有一个非常大的表,这可能不是理想的。我们稍后将讨论如何安全且可预测地替换此类文件。

这完成了表的设置,下一步是输入所需的数据。数据输入与任何 SQL 数据库类似。

INSERT INTO products (name, price, avl) VALUES ('Canvas leash, green, up to 50 kg, 5m', 5.0, 1);
INSERT INTO products (name, price, avl, info) VALUES ('Elastic leash, pink, up to 10 kg, 3m', 12.00, 0, 'A beautiful leash for sophisticated ladies and their four-legged companions');
INSERT INTO products (name, price, avl, info) VALUES ('Pink harness, up to 10 kg', 8.00, 1, 'For room guards released into the street and mistakenly called a dog');
INSERT INTO products (name, price, avl, info) VALUES ('The flexi retractable dog leash, 10 kg, 5m', 7.50, 1, 'A flexi for dogs up to 10 kg. The length is 5 meters, taking into account the length of the owner\'s pulled out arm');
INSERT INTO products (name, price, avl, info) VALUES ('Dog food, 1kg', 4.30, 0, 'Dry food for your pet');
INSERT INTO products (name, price, avl, info) VALUES ('Cat food, 1kg', 2.80, 1, 'If your cat is yelling loudly and demanding food!');
INSERT INTO products (name, price, avl, info) VALUES ('Flea collar for cats , 1kg', 23.20, 1, 'Cats shouldn\'t be flea carriers.');
INSERT INTO products (name, price, avl, info) VALUES ('Flea drops for dogs up to 10 kg', 14.30, 1, 'Drops from uninvited passengers on the skin of your defender');

注意撇号的使用;文本中有一些使用它们的缩写,重要的是用 \ 将它们与其余文本隔离:'Isn\'t it'。Manticore 不支持双引号用于字符串,这将有助于避免转义单撇号。

在上面的第一个请求中,故意省略了 info 字段,以演示如何更新全文字段。需要注意的是,更新文本字段和属性字段的处理方式不同。全文字段使用 REPLACE 命令更新,这会触发新值的重新索引,而 UPDATE 命令足以处理其他字段。这是因为属性字段不参与全文搜索索引过程。

现在,让我们使用 REPLACE 命令向现有记录的某些字段添加数据。要使用此命令,你需要知道要更改或添加信息的行的唯一 ID。首先,我们将通过使用 SELECT * FROM products 获取必要的数据;

SELECT * FROM products WHERE name = 'Canvas leash, green, up to 50 kg, 5m';

select * from products where name... 的结果

确保记住字段的位置。我们稍后需要这些信息。此外,我们需要字段中的所有当前数据,因为替换命令将用这些数据更新整个文件。如果我们不指定所有数据,未指定的字段将被重置。根据字段位置填写 REPLACE 命令。

REPLACE INTO products VALUES (<id>, <info>, <avl>, <price>, <name>);

在开发版本中,您阅读本文时可能已经发布,可以替换特定字段。有关详细信息,请参阅 文档

REPLACE INTO products VALUES (8217224102746783745, 'Sturdy canvas dog leash for 5 meters, suitable for large dog breeds', 1, 5.0, 'Canvas leash, green, up to 50 kg, 5m');

请注意此处的代码,如果您直接从文章中复制命令,表中的ID字段值将不同!如果Manticore找不到指定ID的记录,将会创建一条新记录。

要更新"attributes"字段,可以使用UPDATE命令。顺便提一下,在输入数据时,绿色项圈的价格略有下降:

update products set price = 4.6 where id = 8217224102746783745;

让我们检查结果:

SELECT * FROM products WHERE id = 8217224102746783745;

查询 'where id' 结果的截图

我们已经达到了预期结果,现在让我们尝试搜索,因为我们正在为商店创建产品数据库,以便卖家更容易找到产品。用于在表中搜索的命令是select * from <table> where match('<query>')

SELECT * FROM products WHERE match('harness');
SELECT * FROM products WHERE match ('leash');

查询 'roulette' 的结果

很好,现在数据库能够根据我们通过词形文件创建的连接来回答查询。但似乎输出中缺少了什么?粉色项圈用于室内警卫的条目在哪里?
info字段中,没有像项圈或项圈这样的词,它们只出现在name字段中,因此该条目未包含在输出中。让我们修复这个问题:

SELECT * FROM products WHERE name = 'Pink harness, up to 10 kg';

从 "pink harness" 查询的结果

REPLACE INTO products VALUES (8217224102746783747,'Harness for room guards released into the street and mistakenly called a dog', 1, 8.0, 'Pink harness, up to 10 kg');

让我们检查发生了什么:

SELECT * FROM products WHERE match('harness');

更新表后 'harness' 查询的结果
现在这条记录包含在输出中。从示例中可以看出,只有与索引字段相关的信息参与搜索;其余字段是索引字段的属性。

扩展表

宠物店带来了新货,现在他们还有水族箱设备。为了确保我们能够轻松找到与水族箱相关的词汇,如泵或驱动器,我们需要向我们的词表中添加条目。

标题描述价格可用性
水族箱的泵。带内置过滤器的水族箱泵。容量150升/小时32.00€
水族箱自动过滤器带过滤器的可更换驱动器,容量100升/小时。28.00€
鱼网无痛水族箱鱼网3.00€

让我们将它们添加到数据库中:

INSERT INTO products (name, info, price, avl) VALUES ('The pump for the aquarium.', 'Pump with built-in aquarium filter. Capacity 150 l/h', 32, 1), ('Automatic filter for aquarium', 'Disposable drive with filter, capacity 100 l/h', 28.00, 1), ('Fish net', 'Atraumatic aquarium fish net', 3, 1);

这里我们使用一个命令通过逗号分隔的新行列表进行填充,因此您可以使用一个命令添加大量文档。

让我们检查搜索:

SELECT * FROM products WHERE match ('pump');
SELECT * FROM products WHERE match ('filter');

查询 'pump' 和 'filter' 的结果

好吧,这说明了某些问题。然而,驱动器不被视为泵。这应该添加到我们使用的词汇列表中…
让我们这么做。
哦,这里有一个小问题。这并不容易...
当我们为文本创建搜索系统时,我们会将所有单词放入一个表中,并将它们转换为标记以提高搜索效率。这些标记不会随后更新,以加快搜索过程。然而,有些情况下我们需要更新词形文件并相应地修改标记。让我们更新我们词形文件中的词汇列表,并将产品名称包含在name字段中到搜索索引中。

要更新表中的词形文件,我遵循了以下步骤:

  1. 使用mysqldump创建此表的转储。
  2. 更新词形文件。
  3. 删除旧表。
  4. 在形态学部分创建一个带有更新词形的新表。
  5. 从转储文件中填充新表。
创建转储文件(备份):

在任何不确定的情况下,对表进行备份以防止数据丢失。(这条规则可以贴在墙上作为提醒)。
这也有助于我们实现目标。
要完成这项工作,我们需要断开SQL连接并使用mysqldump工具。

exit;
mkdir /tmp/manticore_dumps
cd /tmp/manticore_dumps
mysqldump -h0 -P9306 -tc --compact manticore products > products.sql

我使用的标志是:

  • -t - 从转储中排除create table语句。
  • -c - 在INSERT命令中指定列名。
  • --compact - 以紧凑格式执行数据库转储,省略检查表可用性、删除它们、创建新表、为创建的表指定配置以及其他部署组织操作的程序。在我们的情况下,这些程序是不必要的,因为我们需要在表中注册一个新的字典文件。
  • manticore - 是mysqldump的数据库名称,使用mysqldump与Manticore时,必须始终是manticore
  • products - 是我们创建转储的表的名称。
  • products.sql - 是转储将上传到的文件的名称。放置文件的目录默认为从mysqldump启动的目录。我建议指定/tmp/以确保示例后续成功运行。或者,您可以输入完整路径:/tmp/manticore_dumps/products.sql

如果您看到:"-- Warning: column statistics not supported by the server." 不用担心,当您使用此mysql工具与Manticore时,这是正常的。

太好了,我们有了第一个转储!
产品转储在文件夹中

更新词形文件:

您是否忘记了词形源文件的位置?

cd /tmp/wordforms

如果您使用MC并且由于某些原因看不到带有文件的列,请尝试使用Ctrl + O组合键。如果没有任何变化,可能是MC没有运行。

词形位置
接下来,使用箭头键进行导航。当需要选择文件时,按 F4 打开所选文件。
添加新字符串:"drive > pump"
带有添加字符串的词形文件
保存并关闭。 F2, Enter, F10
文件已更新。

删除表并创建新表:

在删除表之前,请确保您已备份数据,并且备份中确实包含我们的数据。

cd /tmp/manticore_dumps/

选择备份文件并按 F3 按钮查看它。
您也可以在控制台中使用命令 cat /tmp/manticore_dumps/products.sql 实现相同操作。

您应该看到类似以下内容:
备份视图

好的,让我们继续删除旧表并创建新表:

mysql -h0 -P9306
DROP TABLE products;
CREATE TABLE products (name TEXT, info TEXT, price FLOAT, avl BOOL) morphology = 'stem_en' wordforms='/tmp/wordforms/wf_pet_products.txt';

因此,我们删除了这张表,然后立即重新创建(使用与之前相同的命令,但有一个小改动:现在名称字段也用于文本),现在我们需要向其中添加信息。

exit;
从备份重新填充数据:
mysql -h0 -P9306 < /tmp/manticore_dumps/products.sql
mysql -h0 -P9306

我们已经填充了数据。让我们检查最终结果:

SELECT * FROM products WHERE match ('pump');

很好,全部正常工作!
更新词形后的结果 "select * ... mathc('pump')"

在更新表时,尤其是大型表,存在一个时间段,旧表已被删除而新表尚未创建。在此期间,系统可能会以错误响应请求。为了确保 Manticore 的平稳运行,有几种系统可以帮助避免丢失用户请求。我之后会学习如何实现这些方法。

在本文中,我展示了如何为宠物店的库存设置和使用 Manticore Search。通过词形和词形学,Manticore 通过将相关产品名称和类型链接起来,帮助改进搜索结果。我介绍了如何添加新项目、更新现有项目,并在重大更新(如更改词形文件)期间确保数据一致性。这有助于初学者理解和有效应用 Manticore Search 的功能,使数据搜索更加高效。未来的文章将探索更多功能,让我们继续一起实验 Manticore 以增强您的项目。

今天就到这里。Mike,签收。

结束照片

安装Manticore Search

安装Manticore Search