【问题标题】:How can I Handle strong types over Redis Hashes?如何通过 Redis 哈希处理强类型?
【发布时间】:2016-09-19 05:59:55
【问题描述】:

我的客户端向服务器发送一个 json (JObject),我有一个自定义方法可以将值扁平化为键值对。

假设这是我的 json

{
   Prop1: 12,
   Prop2: "Str",
   Prop3:{
      Prop4: 222.4
   }
}

创建了一个扁平数据字典,如下所示:

"Prop1": 12
"Prop2": "Str"
"Prop3.Prop4": 222.4

现在,我正在使用 RedisStackExchange.Redis 客户端)来保存这些数据。

我生成一个键(例如 obj:123456)并将字典的键值添加为哈希条目。

数据保存在 Redis 上,但我的问题是当我从 Redis 检索数据时需要区分类型。

我注意到IsInteger 标志并想尝试使用它作为开始。 我创建了一个带有整数值的HashEntryIsInteger 是真的),然后是HashSetted 数据。 当我使用HashGet 获取数据时,我注意到 IsInteger 标志为假。

IsInteger 标志在HashSetHashGet 之间丢失是否有任何原因?

有什么简单的方法可以通过 Redis 处理类型(字符串\int\double\date)吗?我可以想到一个自定义实现,但我想去那里。

编辑 - 这是一个代码示例:

Dictionary<string, object> objs = new Dictionary<string, object>
{
    {"Prop1", 12},
    {"Prop2", "Str"},
    {"Prop3.Prop4", 222.4},
};

var redisConnection = ConnectionMultiplexer.Connect(ConfigurationOptions.Parse("localhost:6379,name=SafeRedisConnection,connectTimeout=100000,syncTimeout=100000,abortConnect=false,defaultDatabase=5"));

// just a test
var hashEntries = objs.Where(kvp => kvp.Value is int).Select(kvp => new HashEntry(kvp.Key, (int)kvp.Value));
var hashEntries1 = objs.Where(kvp => kvp.Value is string).Select(kvp => new HashEntry(kvp.Key, (string)kvp.Value));
var hashEntries2 = objs.Where(kvp => kvp.Value is double).Select(kvp => new HashEntry(kvp.Key, (double)kvp.Value));

var arr = hashEntries.Union(hashEntries1).Union(hashEntries2).ToArray();
redisConnection.GetDatabase().HashSet("obj:123456", arr);

var keys = redisConnection.GetDatabase().HashKeys("obj:123456");
var dic = keys.ToDictionary(k => k, k => redisConnection.GetDatabase().HashGet("obj:123456", k));

【问题讨论】:

  • 能否添加关于如何设置数据和获取数据的代码?
  • @YuvalItzchakov - 我添加了一些代码。按类型分离只是我为 IsInteger 测试过的东西。我很高兴在这里了解通过 Redis 获取“类型”的更好做法。
  • 这是一个提供此类功能的库:github.com/elglogins/STRHM
  • @Edward 谢谢。我最终用自定义序列化程序做了类似的事情

标签: c# redis json.net stackexchange.redis


【解决方案1】:

您应该使用自己的 Redis 键命名约定。请记住,在 Redis 中,所有简单值都是 strings(嗯,字节数组......但是 StackExchange.Redis 有一个隐式运算符可以将 RedisValue 转换为 @ 987654322@).

例如,当您在某个 Redis 哈希上添加 pair 时,键可能是 &lt;propertyName&gt;:&lt;type&gt;,这样您就可以再次将键值转换为 CLR 类型...

另一种方法可能是存储该哈希值以及每个哈希值以存储键的数据类型:

var hashEntries = objs.Where(kvp => kvp.Value is int)
                      .Select
                      (
                          kvp => new HashEntry
                          (
                              kvp.Key, 
                              kvp.Value.GetType().AssemblyQualifiedName
                          )
                      );

当您获得部分或全部哈希条目时,您还可以获取其只是元数据对应项来检查每个值类型。

顺便说一句,我认为您应该真正考虑将 JSON 序列化对象注入全局/分区哈希,或使用简单的键字符串键作为全局键空间的一部分,这样您就可以避免这些问题。

如果我需要执行某些操作(例如按某些属性或其他情况索引数据),我会使用散列来存储单个属性...但如果您只是存储完整对象,请考虑我的目的。

【讨论】:

  • 感谢您的回答。我考虑了一些自定义实现(比如你建议的\一个字节数组实现,第一个字节作为“类型”)——但这会破坏我的实现的性能。我使用扁平化技术是有原因的,我希望有更强大的东西。 +1 的努力。
  • @AmirPopovich 但是第一个字节有点过头了,您可以使用密钥命名方案! :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 2013-09-01
  • 2015-04-07
相关资源
最近更新 更多