使用RediSearch对实体进行简单的字符串和整数索引

时间:2019-07-16 07:07:12

标签: redis stackexchange.redis redisearch

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

但是我找不到我需要的方式。

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

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)创建正确的架构索引,也无法理解如何使用NRediSearch Client类正确存储实体。

我不需要全文本或标记化/停用词/等。 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的“想法”之后,这也许会变得晦涩一些。)

1 个答案:

答案 0 :(得分:3)

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

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.html#the_rules_of_text_field_tokenization