数据类型

全文字段和属性

Manticore的数据类型可以分为两类:全文字段和属性。

全文字段

全文字段:

可以使用自然语言处理算法进行索引,因此可以搜索关键词 不能用于排序或分组 可以检索原始文档的内容 可以用于突出显示原始文档的内容 全文字段由数据类型text表示。所有其他数据类型称为“属性”。

属性

属性是与每个文档关联的非全文值,可用于在搜索过程中执行非全文过滤、排序和分组。

通常希望根据匹配文档ID和其排名以及许多其他每个文档的值来处理全文搜索结果。例如,可能需要按日期和相关性对新闻搜索结果进行排序,或在指定价格范围内搜索产品,或将博客搜索限制为由选定用户发布的帖子,或按月份对结果进行分组。为了有效地执行此操作,Manticore不仅允许全文字段,还允许将其他附加属性添加到每个文档。这些属性可用于过滤、排序或分组全文匹配,或仅通过属性进行搜索。

与全文字段不同,属性不是全文索引的。它们存储在表中,但不能像全文那样搜索它们。

属性的一个很好的例子是论坛帖子表。假设只有标题和内容字段需要进行全文搜索 - 但有时还需要将搜索限制为特定作者或子论坛(即仅搜索具有某些特定作者ID或论坛ID的行);或按post_date列对匹配进行排序;或按post_date的月份对匹配的帖子进行分组并计算每组的匹配计数。

该示例演示了运行一个由 author_id、forum_id 过滤并按 post_date 排序的全文查询。

sql

CREATE TABLE forum(title text, content text, author_id int, forum_id int, post_date timestamp);

json

POST /cli -d "CREATE TABLE forum(title text, content text, author_id int, forum_id int, post_date timestamp)"

PHP

  1. $index = new \Manticoresearch\Index($client);
  2. $index->setName('forum');
  3. $index->create([
  4. 'title'=>['type'=>'text'],
  5. 'content'=>['type'=>'text'],
  6. 'author_id'=>['type'=>'int'],
  7. 'forum_id'=>['type'=>'int'],
  8. 'post_date'=>['type'=>'timestamp']
  9. ]);

Python

utilsApi.sql('CREATE TABLE forum(title text, content text, author_id int, forum_id int, post_date timestamp)')

行式和列式属性存储

Manticore支持两种类型的属性存储:

  • 行式 - Manticore Search开箱即用的传统存储
  • 列式 - 由Manticore Columnar Library提供

从它们的名称可以理解,它们以不同的方式存储数据。传统的行式存储:

  • 未经压缩地存储属性
  • 同一文档的所有属性都存储在彼此相邻的一行中
  • 逐行存储
  • 访问属性基本上只需将行ID乘以步幅(单个向量的长度)并从计算出的内存位置获取请求的属性。这提供了非常低的随机访问延迟。
  • 为了获得可接受的性能,属性必须在内存中,否则由于存储的行式特性,Manticore可能不得不读取磁盘上太多不需要的数据,这在许多情况下都是不够优化的。

使用列式存储:

  • 每个属性都独立存储在其单独的“列”中
  • 存储被分成65536条目的块
  • 这些块被压缩存储。这通常允许仅存储少量不同的值,而不是像行式存储中存储所有这些值。高压缩比可以更快地从磁盘读取,并大大降低内存需求
  • 在索引数据时,为每个块独立选择存储方案。例如,如果块中的所有值都相同,则它变为“const”存储,并且仅为整个块存储一个值。如果每个块的唯一值少于256个,则它变为“table”存储,并将索引存储到值表而不是存储值本身
  • 如果清楚请求的值不在块中,则可以提前拒绝在块中进行搜索。

列式存储设计用于处理不适合进入 RAM 的大数据量,因此建议:

  • 如果您有足够的内存容纳所有属性,您将从行式存储中受益
  • 否则,列式存储仍然可以提供体面的性能,内存占用更低,这将允许您在表中存储更多的文档

如何在存储之间切换

传统的行式存储是默认的,因此如果您希望将所有内容以行式方式存储,创建表时无需执行任何操作。

要启用列式存储,您需要:

在CREATE TABLE中指定engine=’columnar’,以使表的所有属性都以列式存储。然后,如果您想将特定属性保留为行式,您需要在声明时添加engine=’rowwise’。例如:

  1. create table tbl(title text, type int, price float engine='rowwise') engine='columnar';

在CREATE TABLE中为特定属性指定engine=’columnar’,使其成为列式存储。例如:

  1. create table tbl(title text, type int, price float engine='columnar');

或者

  1. create table tbl(title text, type int, price float engine='columnar') engine='rowwise';

在普通模式中,您需要在columnar_attrs中列出要作为列式存储的属性。

以下是Manticore Search支持的数据类型列表:

文档标识符

文档标识符是一个强制性的属性,文档ID必须是唯一的 64 位无符号整数。文档 ID 可以明确指定,但如果没有指定,它们仍然是启用的。文档 ID 不可更新。请注意,在检索文档ID时,它们被视为有符号的 64 位整数,这意味着它们可能为负数。如果需要,使用 UINT64() 函数将它们转换为无符号 64 位整数。

显式指定 ID

当您创建表时,可以显式指定ID,但无论您使用什么数据类型,它始终如前面所说 - 一个有符号的64位整数。

CREATE TABLE tbl(id bigint, content text); DESC tbl;

隐式 ID

也可以完全省略指定ID,它将被自动启用。

CREATE TABLE tbl(content text); DESC tbl;

字符数据类型

通用语法:

string|text [stored|attribute] [indexed]

属性

  1. indexed - 全文索引(可用于全文查询)
  2. stored - 存储在文档存储中(存储在磁盘上,而不是在RAM中,延迟读取)
  3. attribute - 使其成为字符串属性(可以按其进行排序/分组) 至少指定一个属性会覆盖所有默认属性(请参阅下文),即如果决定使用自定义属性组合,则需要列出所有所需属性。

未指定属性

stringtext 是别名,但如果不指定任何属性,则它们默认表示不同的含义:

只有 string 默认表示属性(详见下文)。 只有 text 默认表示 stored + indexed(详见下文)。

Text

文本(只有 text 或用于索引的 text/string)数据类型形成表的全文部分。文本字段被索引,可以用于搜索关键字。

文本通过分析器管道传递,将文本转换为单词,应用形态学转换等。最终,从该文本构建了一个全文表(一种特殊的数据结构,可实现对关键字的快速搜索)。

全文字段只能在 MATCH() 子句中使用,不能用于排序或聚合。单词存储在反向索引中,包括它们所属的字段的引用和字段中的位置。这允许在每个字段内搜索单词并使用高级运算符,如接近度。默认情况下,字段的原始文本既被索引又存储在文档存储中。这意味着原始文本可以与查询结果一起返回,并用于搜索结果的高亮显示。

此行为可以通过显式指定文本仅被索引来覆盖。

字段是有名称的,您可以将搜索限制为单个字段(例如,仅搜索“title”)或字段的子集(例如,仅搜索“title”和“abstract”)。您最多可以有256个全文字段。

string

与全文字段不同,字符串属性(仅字符串或字符串/文本属性)按接收到的形式存储,不能用于全文搜索。相反,它们会在结果中返回,可以在 WHERE 子句中用于比较过滤或正则表达式,并且可以用于排序和聚合。通常不建议在字符串属性中存储大文本,而是使用字符串属性存储类似名称、标题、标签、键之类的元数据。

如果您希望还要索引字符串属性,可以同时指定为字符串属性索引。这将允许进行全文搜索并起到属性的作用。

您可以创建一个既是全文字段又作为字符串属性存储的字段。这种方法创建了一个具有相同名称的全文字段和字符串属性。请注意,您不能添加一个存储属性同时将数据存储为字符串属性和在文档存储中。

integer

整数类型允许存储32位无符号整数值。

整数可以通过指定位数而不是 32 位来存储在较短的大小中。例如,如果我们要存储一个我们知道不会超过 8 的数值,类型可以定义为 bit(3)。位数整数的性能较全尺寸的整数慢,但它们需要较少的 RAM。它们以 32 位块保存,因此为了节省空间,它们应该在属性定义的末尾进行分组(否则在两个全尺寸整数之间的位数整数也将占用 32 位)。

Big Integer - 长整型

大整数(bigint)是64位宽的有符号整数。

Boolean

声明一个布尔属性。它等同于一个位数为1的整数属性。

Timestamps

Timestamp 类型表示存储为32位整数的Unix时间戳。不同之处在于,对于Timestamp类型,可以使用时间和日期函数。

Float

实数被存储为32位IEEE 754单精度浮点数。

与整数类型不同,不推荐直接比较两个浮点数是否相等,因为可能存在舍入误差。更可靠的方法是使用近似相等的比较,通过检查绝对误差范围。

另一种替代方案,也可以用于执行类似于 IN(attr, val1, val2, val3) 的操作,是通过选择一个乘法因子,将浮点数转换为整数进行比较。下面的示例说明了如何修改 IN(attr, 2.0, 2.5, 3.5) 以适应整数值。

JSON

这种数据类型允许存储 JSON 对象,对于存储无模式数据非常有用。然而,它不受列式存储的支持。但是,它可以存储在传统的存储中,因为可以在同一张表中组合两种存储类型。

JSON 属性可用于大多数操作。还有一些特殊的函数,如 ALL()、ANY()、GREATEST()、LEAST() 和 INDEXOF(),允许遍历属性数组。

文本属性与字符串相同,因此无法在全文匹配表达式中使用它们。但是,可以使用字符串函数,如 REGEX()。

在处理 JSON 属性时,在某些情况下可能需要强制执行数据类型以确保正确的功能。例如,在处理浮点值时,必须使用 DOUBLE() 进行正确的排序。

Multi-value integer

Multi-value integer (MVA) 允许存储可变长度的 32 位无符号整数列表。这对于存储一对多的数值,如标签、产品类别和属性,可能是有用的。

它支持过滤和聚合,但不支持排序。可以使用需要至少一个元素通过(使用 ANY())或所有元素通过(ALL())的条件进行过滤。

可以提取最小或最大元素以及列表的长度等信息。一个示例展示了通过多值属性的最小元素进行排序。