2016-02-27 70 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

相關問題