У меня есть список keys
, которые я хочу получить от Redis
. Я написал такую функцию, но она возвращает все:
public IOrderedEnumerable<Fields> GetValues(List<string> symbols)
{
var retVal = new List<Fields>();
var patternStr = "[";
int count = 0;
foreach (var symbol in symbols)
{
patternStr += (symbol);
if (++count != symbols.Count)
{
patternStr += ", ";
}
}
patternStr += "]*";
foreach (var ep in redis.GetEndPoints())
{
var server = redis.GetServer(ep);
var keysList = server.Keys(database: 0, pattern: patternStr).ToList();
var keys = keysList.ToArray();
Console.WriteLine("Number of Symbols in this range{0} ", keys.Length);
foreach (var rk in keys)
{
var myValTask = db.StringGetAsync(rk.ToString());
var myVal = myValTask.Result;
var jsonStr = myVal.ToString();
...
}
...
}
...
Я считаю, что часть кода является проблемой. Я просто хочу, чтобы Redis
возвращал subset
из keys
, и я создаю шаблон, разделяя их "," :
var patternStr = "[";
int count = 0;
foreach (var symbol in symbols)
{
patternStr += (symbol);
if (++count != symbols.Count)
{
patternStr += ", ";
}
}
patternStr += "]*";
Я знаю, что могу получить все ключи, а затем отфильтровать их, как только получу, но я хочу избежать перегрузки сети...
Изменить 1
Кстати, ключи выглядят так:
127.0.0.1:6379> keys *
1) "BBWI_2022-08-19"
2) "ABBV_2023-01-20"
3) "ZTS_2022-10-21"
Если я правильно понимаю, у вас есть набор дискретных ключей, которые вы хотите получить одним пакетом. Если это так, вы можете получить все элементы (в разумных пределах, скажем, < 1000 за раз), передав RedisKey[]
массив в StringGetAsync
:
var keys = symbols.Select(symbol => (RedisKey)symbol).ToArray();
var values = await db.StringGetAsync(keys);
// .. use values
Вы можете использовать команду Scan
на сервере Redis следующим образом:
public async Task<List<string>> ScanKeysAsync(string match, string count)
{
var schemas=new List<string>();
int nextCursor = 0;
do
{
RedisResult redisResult =await _redisServer.ExecuteAsync("SCAN", nextCursor.ToString(), "MATCH", match, "COUNT", count);
var innerResult = (RedisResult[])redisResult;
nextCursor = int.Parse((string)innerResult[0]);
List<string> resultLines = ((string[])innerResult[1]).ToList();
schemas.AddRange(resultLines);
}
while (nextCursor != 0);
return schemas;
}
а в вашем случае будет примерно так:
var keys=await ScanKeysAsync("BBWI*",10);//return max 10 occurance of pattern
Но я рекомендую использовать Scan
в очень особых сценариях, потому что он действует как курсор и будет перебирать все ключи в Redis, чтобы найти совпадение, а также, пожалуйста, прочитайте этот https://redis.io/commands/scan
Контрольная работа
var redis = scope.ServiceProvider.GetRequiredService<IDatabase>();
await redis.StringSetAsync("BBWI_2022-08-19", "test1",TimeSpan.FromMinutes(5));
await redis.StringSetAsync("BBWI_20fd22-08-19", "test2", TimeSpan.FromMinutes(5));
await redis.StringSetAsync("ABBV_2023-08-19", "test3", TimeSpan.FromMinutes(5));
var foundKeys = await ScanKeysAsync("BBW*", "10");
//BBWI_2022-08-19
//BBWI_20fd22-08-19
К сожалению, строка RedisResult redisResult = await server.ExecuteAsync("SCAN", nextCursor.ToString(), "MATCH", match, "COUNT", count); никогда не возвращается.
Я протестировал его и отлично работает, ответ обновлен и добавлен тестовый пример
Я смог обойти это, поэтому я отдал вам должное. Дело в том, что я хочу получить все символы в пакете. Я не знаю, как построить строку запроса для всех символов сразу. Я не имею в виду все ключи в базе данных, я имею в виду свое собственное подмножество.
Спасибо. Но как выглядит символ? См. Edit 1 в op, чтобы увидеть, как на самом деле выглядят клавиши. Я не знаю, как построить строку запроса?