4

我需要在 Redis 中存储简单的实体对象 (C#)。我还需要使用二级索引和精确匹配来搜索它们。在为 Redis natvie 数据类型苦苦挣扎之后,我选择尝试使用 RediSearch 来完成这项任务。

但是我找不到如何以我需要的方式使用它。

我的目标很简单。实体数据结构非常简单。例如,我有一个Device听起来像这样的类(我省略了大多数不得索引的字符串/整数字段,因此与示例无关):

public class Device 
{
    public int Id { get; set; } // primary key
    public string Name { get; set; } // no indexing on this
    public string SerialNumber { get; set; } // this is indexed and unique
    public string ServerNode { get; set; } // this is indexed
    public int Status { get; set; } // this is indexed, possible values 0..4
    public string Info { get; set; } // no indexing on this
}

我需要存储Device类的实例并检索它们:

  • 单独地,通过SerialNumber
  • 作为ServerNode和/或的列表Status

我正在从 MySQL 切换到 Redis,并且只是为了制作一个 sql 等效项,我正在尝试复制这些 sql-where 子句中的任何一个:

  • WHERE SerialNumber = 'RK01:"12345678"'
  • WHERE ServerNode = 'Node-US-01'
  • WHERE Status BETWEEN 1 AND 3
  • WHERE ServerNode = 'Node-IT-04' AND Status = 4

我的项目是用 C# 编写的,并且我已经开始使用 StackExchange.Redis 和 NRediSearch 包。

我无法弄清楚如何创建正确的模式索引(通过 redis-cli),也无法理解如何使用 NRediSearchClient类正确存储实体。

我不需要任何全文或标记化/停用词/等。RediSearch 的功能,只是“简单的纯”文本和整数索引。

我的第一个问题是字符串中存在标点符号(主要是连字符,但在某些情况下还有双引号)。

我创建了一个基于TAGNUMERIC字段类型的架构:

FT.CREATE Device NOHL NOOFFSETS NOFREQS STOPWORDS 0 SCHEMA Id NUMERIC SORTABLE SerialNumber TAG SORTABLE ServerNode TAG SORTABLE Status NUMERIC SORTABLE

我尝试通过以下方式通过 NRediSearch 添加“文档”(但也通过 redis-cli 进行测试):

通过 redis-cli:

FT.ADD Device obj:Device:1 1.0 FIELDS Id 1 Name "FoobarDevice" SerialNumber "RK01:\"12345678\"" ServerNode "Node-US-01" Status 1 Info "this and that"

通过 NRediSearch

var rsc = new Client("Device", redis_database);
var doc = new Document("obj:Device:1");
doc.Set("Id", 1);
doc.Set("Name", "FoobarDevice");
doc.Set("SerialNumber", "RK01:\"12345678\"");
doc.Set("ServerNode", "Node-US-01");
doc.Set("Status", 1);
doc.Set("Info", "this and that");
rsc.AddDocument(doc);

如果我在 redis-cli 中键入任何这些命令,我​​会在屏幕上转储正确的设备实体: > FT.GET Device obj:Device:1> HGETALL obj:Device:1

现在的问题是:我无法对这些索引执行任何查询。首先,我不清楚命令行上正确的查询语法;以下是一些无效的示例:

>FT.SEARCH Device @ServerNode:{Node-US-01}

>FT.SEARCH Device "@ServerNode:{Node-US-01}"

>FT.SEARCH Device @ServerNode:"{Node-US-01}"

>FT.SEARCH Device @ServerNode:{"Node-US-01"}

>FT.SEARCH Device @SerialNumber:{RK01:\"12345678\"}

我要么收到语法错误,要么没有结果。

我知道序列号字符串有点奇怪,但我无法更改它的格式。

我应该在文档中存储转义版本的字符串值吗?哪个是重现与类似 sql 的 where 子句相同的结果的正确语法?以及如何处理在值本身中包含双引号 (") 的字段值的字符串搜索?

最后但并非最不重要的一点是,我找不到任何关于使用 NRediSearch Query 类和 QueryBuilder 命名空间的说明性示例或文档(但在我了解 RediSaerch 如何“思考”之后,这可能会变得不那么晦涩难懂)。

4

1 回答 1

6

您索引数据就好了,唯一的问题是您的搜索查询。您的数据包含 RediSearch 自动标记化的字符(如-:)。为了避免tokanization,您需要在查询中转义它们。请注意,当使用 redis-cli 时,您必须进行双重转义,以便转义字符 ( \) 实际上会发送到 redis。由于"它的问题更大,您必须在查询和 redis-cli 中对其进行转义,因此您需要三个转义(两个转义字符将被发送到 redis,一个在 cli 中转义)。它看起来像这样:

127.0.0.1:6379> FT.SEARCH Device "@ServerNode:{Node\\-US\\-01}"
1) (integer) 1
2) "obj:Device:1"
3)  1) Id
    2) "1"
    3) Name
    4) "FoobarDevice"
    5) SerialNumber
    6) "RK01:\"12345678\""
    7) ServerNode
    8) "Node-US-01"
    9) Status
   10) "1"
   11) Info
   12) "this and that"
127.0.0.1:6379> FT.SEARCH Device "@SerialNumber:{RK01\\:\\\"12345678\\\"}"
1) (integer) 1
2) "obj:Device:1"
3)  1) Id
    2) "1"
    3) Name
    4) "FoobarDevice"
    5) SerialNumber
    6) "RK01:\"12345678\""
    7) ServerNode
    8) "Node-US-01"
    9) Status
   10) "1"
   11) Info
   12) "this and that"

你可以在这里阅读更多关于tokanization和转义的信息:https ://oss.redislabs.com/redisearch/Escaping/

于 2019-07-16T07:52:04.970 回答