Как я могу обрабатывать сильные типы по хэшам Redis?

Мой клиент отправляет на сервер json (JObject), и у меня есть собственный метод, который сводит значение в пару ключ-значение.

Предполагая, что это мой json

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

Создается словарь сглаженных данных, который выглядит следующим образом:

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

Теперь я использую Redis (клиент StackExchange.Redis) для хранения этих данных.

Я генерирую ключ (например, obj:123456) и добавляю значения ключа словаря в виде хэш-записей.

Данные сохраняются в Redis, но проблема в том, что мне нужно различать типы при извлечении данных из Redis.

Я заметил флаг IsInteger и хотел попробовать использовать его для начала. Я создал HashEntry с целочисленным значением (IsInteger было правдой), а затем HashSetted данные. Когда я извлекал данные с помощью HashGet, я заметил, что флаг IsInteger был ложным.

Есть ли причина, по которой флаг IsInteger теряется между HashSet и HashGet?

Есть ли какой-нибудь тривиальный способ обработки типов (string\int\double\date) в Redis? Я могу придумать пользовательскую реализацию, но я бы хотел пойти туда.

Изменить. Вот пример кода:

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));

person Amir Popovich    schedule 22.05.2016    source источник
comment
Не могли бы вы добавить код того, как вы устанавливаете данные и получаете данные?   -  person Yuval Itzchakov    schedule 22.05.2016
comment
@YuvalItzchakov - я добавил немного кода. Разделение по типу — это то, что я тестировал для IsInteger. Я был бы рад рассказать здесь о лучших методах получения типов через Redis.   -  person Amir Popovich    schedule 22.05.2016
comment
Вот библиотека, обеспечивающая такую ​​функциональность: github.com/elglogins/STRHM.   -  person Edward    schedule 03.02.2019
comment
@Эдвард Спасибо. Я закончил тем, что сделал что-то подобное с пользовательским сериализатором   -  person Amir Popovich    schedule 03.02.2019


Ответы (1)


Вам следует поиграть со своими собственными соглашениями об именах ключей Redis. И помните, что в Redis все простые значения являются строками (ну, массивами байтов... но StackExchange.Redis имеет неявный оператор для преобразования RedisValue в string).

Например, когда вы добавляете pair к некоторому хэшу Redis, ключ может быть <propertyName>:<type>, и таким образом вы можете снова работать над преобразованием значений ключа в типы CLR...

Другой подход может заключаться в сохранении этих хэшей вместе с другим хешем для каждого из них для хранения типов данных ключей:

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

Всякий раз, когда вы получаете некоторые или все записи хэша, вы можете также получить его аналог просто метаданные для проверки каждого типа значения.

Кстати, я считаю, что вам действительно следует подумать о внедрении сериализованных объектов JSON в глобальный/разделенный хэш или об использовании простых ключей строки ключей как части глобального пространства ключей, и вы избежите этих проблем.

Я бы использовал хэши для хранения отдельных свойств, если мне нужно выполнить некоторые операции, такие как индексирование данных по какому-либо свойству или другим случаям... но если вы просто храните полные объекты, рассмотрите мой целенаправленный подход.

person Matías Fidemraizer    schedule 22.05.2016
comment
Спасибо за ответ. Я думал о некоторых пользовательских реализациях (например, та, которую вы предложили, реализация массива байтов с первым байтом в качестве типа) - но это убьет производительность моей реализации. Я использую технику сглаживания по какой-то причине, и я надеялся на что-то более надежное. +1 за усилия. - person Amir Popovich; 22.05.2016
comment
@AmirPopovich Но первый байт - это излишество, вы можете использовать схему именования ключей! :D - person Matías Fidemraizer; 22.05.2016