2016-02-27 66 views
-2

鉴于这种LogStash事件,红宝石散列Logstash过滤器 - 从 “this_is_example”=> 1转换键名称为[此] [是] [示例] => 1

{ 
    "_some_private_key" => 10, 
    "address_unit" => "1", 
    "address_sqft" => 1098, 
    "address_city" => "NEW YORK", 
    "apartment_floor_unit_door" => "5", 
    "tags" => [ 
     "pub", 
     "importer", 
     "assessment" 
    ] 
} 

应该被存储到ES作为

{ 
    "_some_private_key": 10, 
    "address": { 
    "unit": 1, 
    "sqft": 1098, 
    "city": "NEW YORK" 
    }, 
    "apartment": { 
    "floor" : { 
     "unit": { 
     doors: 1043 
     } 
    } 
    }, 
    "tags": [ 
    "pub", 
    "importer", 
    "assessment" 
    ] 
} 

约束:

  • 应该绕过键开始_
  • 应该是动态/递归,检查重点apartment_floor_unit_door例如

我想知道是否有一些内置/社区过滤器来实现它,或如何使用Ruby代码来实现它。

谢谢!

回答

1

与mudasobwas类似,但使用each_with_object代替。我更喜欢inject这种方法只要有可能(each_with_object只有可变对象的作品,因为你不会在块的最后返回一个新的对象)

def convert(hash) 
    hash.each_with_object({}) do |(key, value), akku| 
    if (parts = key.split('_')).length == 2 
     akku[parts[0]] ||= {} 
     akku[parts[0]][parts[1]] = value 
    else 
     akku[key] = value 
    end 
    end 
end 

而且我没有使用正则表达式(只能通过.split()间接的),因为我认为这更可读)。

您是否需要处理带有多个下划线的密钥?或更多层次的嵌套?

UPDATE:

def convert(input) 
    input.each_with_object({}) do |(key, value), output| 
    next if key.start_with?('_') 
    keys = key.split('_') 
    convert_keys(output, keys, value) 
    end 
end 

def convert_keys(output, keys, value) 
    keys[0...-1].each do |key| 
    output = output[key] ||= {} 
    end 
    output[keys.last] = value 
end 

这应该做的伎俩。这不是递归的,因为你的样品输入内容不要求(如果输入的散列值又是需要被打破键的哈希不工作)。 convert_keys方法也可以递归地完成。但我更喜欢这里的迭代方法。

这是否解决问题吗?

+0

帕斯卡尔,谢谢你的回答!我没有说明它需要动态。我用更多的信息更新了这个问题,包括约束条件。你的代码几乎在那里,它只需要动态/递归。你还能帮忙吗?谢谢! – CodeWarrior

+0

非常感谢,你帮了很多!请继续这样,所以需要像你这样的人了解什么是互相帮助。今天SO是关于一群有知识的人,当人们去那里寻求帮助时,他们能做的最好的事情就是说:在Google上搜索并在30分钟内学习它,BULLSHIT!欢呼的人,你摇滚,并保存我的**!是啊! – CodeWarrior

0
inp = { 
    "address_unit" => "1", 
    "address_sqft" => 1098, 
    "address_city" => "NEW YORK", 
    "tags" => ["pub", "importer", "assessment"] 
} 

inp.inject({}) do |memo, (k, v)| 
    if k =~ /\A(.*?)_(.*)/ 
    (memo[$~[1]] ||= {})[$~[2]] = v 
    else 
    memo[k] = v 
    end 
    memo 
end 

#⇒ { 
# "address" => { 
#  "city" => "NEW YORK", 
#  "sqft" => 1098, 
#  "unit" => "1" 
# }, 
#  "tags" => [ 
# [0] "pub", 
# [1] "importer", 
# [2] "assessment" 
# ] 
# } 

上面的代码将打破所有强调的foo_bar键嵌套。

+0

嗨!几乎在那里!我更新了添加约束条件的问题。感谢您的帮助! – CodeWarrior

+0

你误解了SO的工作原理。没有人会为你写一个代码。 – mudasobwa

+0

我不会误解SO的工作方式,像你这样的人是如此摧毁它,也知道删除我的旧评论不会改变它;) – CodeWarrior

0

鉴于你的榜样(三场),怎么样logstash解决方案:

mutate { 
    rename => { "address_unit" => "[address][unit]" } 
    rename => { "address_sqft" => "[address][sqft]" } 
    rename => { "address_city" => "[address][city]" } 
} 

我没有看,看看是否可以重命名一次性做多,那么你可以尝试这一点。

+0

对不起,但它需要是动态的。我更新了这个问题以反映真正的需求。谢谢! – CodeWarrior

相关问题