복붙노트

[REDIS] ServiceStack 레디 스, 어떻게 목록으로 루아 테이블을 반환

REDIS

ServiceStack 레디 스, 어떻게 목록으로 루아 테이블을 반환

나는 ServiceStack에서 레디 스 클라이언트를 사용하고 있습니다. 나는 몇 레디 스 호출에서 결과 루아 테이블을 채우는 루아 스크립트가 있습니다. 나는 어떤 방법으로이 테이블을 반환합니다. 내 생각은 단지 "를 반환 myTable에"를 할 클라이언트 LIB에서와 루아 스크립트의 방법 ExecLuaShaAsList를 사용하는 것이 었습니다. 그것은 내가 항상 빈 목록 등을 얻을 작업을 나던.

어떻게 레디 스 클라이언트에 루아 테이블을 반환?

레디 스 클라이언트와이는 C # 스크립트 내가 사용 :

using (var redisClient = GetPooledRedisClient())
{
    var sha1 = redisClient.LoadLuaScript(luaBody);
    List<string> theList = redisClient.ExecLuaShaAsList(sha1);
    int listLength = theList.Count(); //listLength is always 0 for some reason
}

아래 답변 FROM 팁 AFTER UPDATE

이 LuaBody 만드는 방법입니다 :

    private string GetLuaScript(List<CatalogItem> categories, List<CatalogItem> products)
    {
        string categoriesToAggregate = string.Join("\",\"", categories.Select(c=>c.Name));
        categoriesToAggregate = "\"" + categoriesToAggregate + "\"";

        string csSearchResult = string.Join("\",\"", products.Select(c => c.Name));
        csSearchResult = "\"" + csSearchResult + "\"";


        StringBuilder sb = new StringBuilder();
        sb.AppendLine("local categoriesToAggregate = {").Append(categoriesToAggregate).Append("}                        ");
        sb.AppendLine("local csSearchResult = {").Append(csSearchResult).Append("}                                      ");
        sb.AppendLine("local result = {}                                                                                ");
        sb.AppendLine();
        sb.AppendLine("for i=1,#categoriesToAggregate do                                                                ");
        sb.AppendLine(" result[categoriesToAggregate[i]] = 0                                                            ");
        sb.AppendLine();
        sb.AppendLine(" for j=1,#csSearchResult do                                                                      ");
        sb.AppendLine("     local fieldValue = redis.call('hget', 'asr:'..csSearchResult[j], categoriesToAggregate[i])  ");
        sb.AppendLine("     if fieldValue then                                                                          ");
        sb.AppendLine("         result[categoriesToAggregate[i]] = result[categoriesToAggregate[i]] + fieldValue        ");
        sb.AppendLine("     end                                                                                         ");
        sb.AppendLine(" end                                                                                             ");
        sb.AppendLine("end                                                                                              ");
        sb.AppendLine();
        sb.AppendLine("return cjson.encode(result)                                                                      ");

        return sb.ToString();
    }

해결법

  1. ==============================

    1.루아에서, 당신은 루아 배열 또는 JSON 개체를 반환해야합니다. 루아 인터프리터 내부에서만 유효 핸들처럼 'myTable에'소리. 그 핸들은 호출 후 바로 정리되어 있으므로 클라이언트에 전달되지 않습니다.

    루아에서, 당신은 루아 배열 또는 JSON 개체를 반환해야합니다. 루아 인터프리터 내부에서만 유효 핸들처럼 'myTable에'소리. 그 핸들은 호출 후 바로 정리되어 있으므로 클라이언트에 전달되지 않습니다.

    편집 : 간단한 루아 테이블 / 배열이 지원되어야한다. 확실하지 무슨 일이 스크립트를 보지 않고, 다음에거야.

    또한 루아 스크립트의 자성에 대한 몇 가지 추가 정보를 원하시면,이 SO 링크를 참조하십시오.

    이, TW 도움이되기를 바랍니다

    ON 편집 후 :

    이는 영업 이익의 원래 루아 스크립트했다 :

    local a={}
    for i = 1, 1, 1 do
      a["47700415"] = redis.call('hget', 'asr:47700415', 'MDEngines')
      a["47700415_000"] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
    end
    return a
    

    답변 : 당신은 루아 반환 값에 중첩 된 값을 반환 할 수 없습니다. 당신이 당신의 ServiceStack 기능에서 볼 수 있듯이, 루아 스크립트 목록을 반환하고, 목록이 중첩되지 않습니다.

    여기에 두 가지 솔루션은, JSON을 가진 사람은 약간의 오버 헤드를 제공합니다 (그러나 프로그래밍 할 때 쉽게 할 수 있으며 빈 채로-안전하다).

    A : 사용 cjson

    local a={}
    for i = 1, 1, 1 do
      a["47700415"] = redis.call('hget', 'asr:47700415', 'MDEngines')
      a["47700415_000"] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
    end
    return cjson.encode(a)
    

    MsgPack도 아주 좋은 소형 직렬화 형식 (우리가 많이 사용)이며, 다음과 같이 반환 할 수 있습니다 :

    A-고도 : cmsgpack 사용

    return cmsgpack.pack(a)
    

    B : 간단한 배열을 사용

    local a={}
    for i = 1, 1, 1 do
      a[1] = "47700415"
      a[2] = redis.call('hget', 'asr:47700415', 'MDEngines')
      a[3] = "47700415_000"
      a[4] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
    end
    return a
    

    이 반환 :

    ㅏ:

    tw@srv-flux-02:~$ redis-cli -p 14312 EVAL "$(cat ~/tw_luatest.lua)" 0 0
    "{\"47700415\":\"Hello\",\"47700415_000\":\"World\"}"
    

    비:

    tw@srv-flux-02:~$ redis-cli -p 14312 EVAL "$(cat ~/tw_luatest2.lua)" 0 0
    1) "47700415"
    2) "Hello"
    3) "47700415_000"
    4) "World"
    

    당신이 볼 수 있듯이, 나는 HSET의 일부 더미 데이터를 넣어.

    인트로 투 루아를 위해 레디 스 프로그래머 : 나는 또한이 링크, 거기에 몇 가지 좋은 정보를 추천 할 수 있습니다

    루아 딕셔너리에 값을 추가하는 좋은 방법은 여기에서 볼 수있다 :

    local fkeys = redis.call('sinter', unpack(KEYS))
    local r = {}
    for i, key in ipairs(fkeys) do
      r[#r+1] = redis.call('hgetall',key)
    end
    return r
    
  2. from https://stackoverflow.com/questions/22287334/servicestack-redis-how-to-return-lua-table-as-list by cc-by-sa and MIT license