<p>也许有更好的方法来解决这个特定的问题(使用一些ElasticSearch库或其他东西),但是这里有一个Clojure的解决方案,使用您请求的输入和输出数据格式。在</p>
<p>我把这个测试数据放在一个名为<code>data.json</code>的文件中:</p>
<pre><code>{
"agg": {
"agg1": [
{
"keyWeWant": "*-20.0",
"asdf": 0,
"asdf": 20,
"asdf": 14,
"some_nested_agg": [
{
"keyWeWant2": 20,
"to": 25,
"doc_count": 4,
"some_nested_agg2": {
"count": 7,
"min": 2,
"max": 5,
"keyWeWant3": 2.857142857142857,
"sum": 20
}
},
{
"keyWeWant2": 25,
"to": 30,
"doc_count": 10,
"some_nested_agg2": {
"count": 16,
"min": 2,
"max": 10,
"keyWeWant3": 6.375,
"sum": 102
}
}]
}]}
}
</code></pre>
<p>然后,<a href="https://github.com/dakrone/cheshire" rel="nofollow">Cheshire JSON library</a>将数据解析为Clojure数据结构:</p>
^{pr2}$
<p>接下来,要获取的路径定义如下:</p>
<pre><code>(def my-data-map
{"keyWeWant" ["agg", "agg1"],
"keyWeWant2" ["agg", "agg1", "some_nested_agg"],
"keyWeWant3" ["agg", "agg1", "some_nested_agg", "some_nested_agg2"]})
</code></pre>
<p>上面的<code>data_map</code>没有“:”,单引号改为双引号,最后一个“keyWeWant”改为“keyWeWant3”。在</p>
<p>下面的<code>find-nested</code>具有Clojure的<a href="https://clojuredocs.org/clojure.core/get-in" rel="nofollow">^{<cd4>}</a>的语义,只有这样它才能在带有向量的映射上工作,并返回所有值而不是一个值。
当给<code>find-nested</code>一个搜索向量时,它会在一个嵌套映射中找到所有值,其中一些值可以由一个带有映射列表的向量组成。矢量中的每个贴图都会被检查。在</p>
<pre><code>(defn find-nested
"Finds all values in a coll consisting of maps and vectors.
All values are returned in a tree structure:
i.e, in your problem it returns (20 25) if you call it with
(find-nested ['agg', 'agg1', 'some_nested_agg', 'keyWeWant2']
my-data).
Returns nil if not found."
[ks c]
(let [k (first ks)]
(cond (nil? k) c
(map? c) (find-nested (rest ks) (get c k))
(vector? c) (if-let [e (-> c first (get k))]
(if (string? e) e ; do not map over chars in str
(map (partial find-nested (rest ks)) e))
(find-nested ks (into [] (rest c)))) ; create vec again
:else nil)))
</code></pre>
<p><code>find-nested</code>查找搜索路径的值:</p>
<pre><code>(find-nested ["agg", "agg1", "some_nested_agg", "keyWeWant2"] my-data)
; => (20 25)
</code></pre>
<p>如果指向“keyWeWant”的所有路径都映射到<code>my-data</code>上,则这些是<code>tree</code>的切片:</p>
<blockquote>
<p>(*-20.0<br/>
(20 25)<br/>
(2.857142857142857 6.375))</p>
</blockquote>
<p>您所要求的结构(所有路径到达的最终结果)可以从<code>function-name</code>中的<code>tree</code>获得,如下所示:</p>
<pre><code>(defn function-name
"Transforms data d by finding (nested keys) via data-map m in d and
flattening the structure."
[d m]
(let [tree (map #(find-nested (conj (second %) (first %)) d) m)
leaves (last tree)
leaf-indices (range (count leaves))
results (for [index leaf-indices]
(map (fn [slice]
(if (string? slice)
slice
(loop [node (nth slice index)]
(if node
node
(recur (nth slice (dec index)))))))
tree))
results-with-paths (mapv #(zipmap (keys m) %) results)
json (cheshire/encode results-with-paths)]
json))
</code></pre>
<p>如果<code>results</code>大于特定的片,则<code>results</code>使用<a href="https://clojuredocs.org/clojure.core/loop" rel="nofollow">^{<cd12>}</a>后退一步。我认为对于更深层次的嵌套结构也会有效果——如果下一个切片的大小始终是前一个切片的两倍,或者应该是相同的大小,但我还没有对其进行测试。在</p>
<p>{{cd7>请求的{cd7>}将导致<cd16}格式的<cd16}:</p>
<blockquote>
<p>[{<br/>
"keyWeWant": "<em>-20.0",<br/>
"keyWeWant2": 20,<br/>
"keyWeWant3": 2.857142857142857 }<br/>
{<br/>
"keyWeWant": "</em>-20.0",<br/>
"keyWeWant2" 25,<br/>
"keyWeWant3" 6.375 }]</p>
</blockquote>
<p>/编辑
我知道你在寻找一个相对简单的解决方案,但事实并非如此。:-)可能有一个库中没有它。我很乐意知道如何简化它。在</p>