Aerospike:如何将整数列表批量加载到容器中?

Aerospike: how to bulk load a list of integers into a bin?

我正在尝试使用 Aerospike bulk loader 使用制表符分隔文件中的数据为集群播种。

源数据如下所示:

set key segments
segment 123 10,20,30,40,50
segment 234 40,50,60,70

第三列 'segments' 包含以逗号分隔的整数列表。

我创建了一个 JSON 模板:

{
  "version" : "1.0",
  "input_type" : "csv",
  "csv_style": { "delimiter": " " , "n_columns_datafile": 3, "ignore_first_line": true}

  "key": {"column_name":"key", "type": "integer"},

  "set": { "column_name":"set" , "type": "string"},

  "binlist": [
    {"name": "segments",
      "value": {"column_name": "segments", "type": "list"}
    }
  ]
}

... 和 运行 加载程序:

java -cp aerospike-load-1.1-jar-with-dependencies.jar com.aerospike.load.AerospikeLoad -c template.json data.tsv

当我在aql中查询记录时,它们似乎是一个字符串列表:

aql> select * from test
+--------------------------------+
| segments                       |
+--------------------------------+
| ["10", "20", "30", "40", "50"] |
| ["40", "50", "60", "70"]       |
+--------------------------------+

我要存储的数据是一个整数列表。是否有一种简单的方法可以将存储在此容器中的对象转换为整数列表(可能是 Lua UDF)或者可以对批量加载器模板进行调整?

更新:

我试图通过创建 Lua UDF 将列表从字符串转换为整数来解决这个问题:

function convert_segment_list_to_integers(rec)
    for i=1, table.maxn(rec['segments']) do
        rec['segments'][i] = math.floor(tonumber(rec['segments'][i]))
    end
    aerospike:update(rec)
end

...注册了它:

aql> register module 'convert_segment_list_to_integers.lua'

... 然后尝试对我的集合执行:

aql> execute convert_segment_list_to_integers.convert_segment_list_to_integers() on test.segment

我启用了一些更详细的日志记录并注意到 UDF 正在抛出错误。显然,它期待 table 并通过了 userdata:

Dec 04 2015 23:23:34 GMT: DEBUG (udf): (udf_rw.c:send_result:527) FAILURE when calling convert_segment_list_to_integers convert_segment_list_to_integers ...rospike/usr/udf/lua/convert_segment_list_to_integers.lua:2: bad argument #1 to 'maxn' (table expected, got userdata)
Dec 04 2015 23:23:34 GMT: DEBUG (udf): (udf_rw.c:send_udf_failure:407) Non-special LDT or General UDF Error(...rospike/usr/udf/lua/convert_segment_list_to_integers.lua:2: bad argument #1 to 'maxn' (table expected, got userdata))

maxn 似乎不适用于 userdata 对象。

你能看出需要做些什么来解决这个问题吗?

要将包含字符串值的列表转换为整数值列表,您可以 运行 以下记录 udf:

function convert_segment_list_to_integers(rec)
        local list_with_ints = list()
        for value in list.iterator(rec['segments']) do
                local int_value = math.floor(tonumber(value))
                list.append(list_with_ints, int_value)
        end
        rec['segments'] = list_with_ints
        aerospike:update(rec)
end

编辑现有 lua 模块时,请确保重新运行 register module 'convert_segment_list_to_integers.lua'

此问题的原因在于 aerospike-loader 工具:它总是 assume/enforce 字符串,如您在以下 java 代码中所见:

case LIST:
    /*
     * Assumptions
     * 1. Items are separated by a colon ','
     * 2. Item value will be a string
     * 3. List will be in double quotes
     * 
     * No support for nested maps or nested lists
     * 
     */
    List<String> list = new ArrayList<String>();
    String[] listValues = binRawText.split(Constants.LIST_DELEMITER, -1);
    if (listValues.length > 0) {
        for (String value : listValues) {
            list.add(value.trim());
        }
        bin = Bin.asList(binColumn.getBinNameHeader(), list);
    } else {
        bin = null;
        log.error("Error: Cannot parse to a list: " + binRawText);
    }
    break;

Github 上的来源:http://git.io/vRAQW

如果您愿意,可以修改此代码并重新编译以始终采用整数列表值。将第 266 和 270 行更改为如下内容(未经测试):

List<Integer> list = new ArrayList<Integer>(); 
list.add(Integer.parseInt(value.trim());