【问题标题】:Convert dot-notation JSON into elastic search deeply nested query JSON, with bodybuilder.js?使用 bodybuilder.js 将点符号 JSON 转换为弹性搜索深度嵌套查询 JSON?
【发布时间】:2018-11-22 17:59:42
【问题描述】:

如果我有一个使用点表示法表示深度的平面数据结构。看起来是这样的:

 { 
   "key1": "name1",
   "key2.subKey.finalKey": "name2"
 }

我正在使用它来创建我的查询:

let query = _.reduce(jsonQuery, (queryBody, queryValue, queryName)=>{
    return queryBody.query("term", "queryName", "queryValue")
}, bodybuilder())

我已经简化了,但这绝不会处理伪嵌套数据。

我有一个可以将点符号转换为嵌套的函数。

以下是健美运动员建议使用嵌套结构的方法:

bodybuilder()
  .query('nested', 'path', 'obj1', (q) => {
    return q.query('match', 'obj1.color', 'blue')
  })
  .build()

这将导致以下查询结构:

{
  "query": {
    "nested": {
      "path": "obj1",
      "query": {
        "match": {
          "obj1.color": "blue"
        }
      }
    }
  }
}

所以在我的多嵌套版本中,我希望得到:

{
  "query": {
    "nested": {
      "path": "key2",
      "query": {
        "nested": {
          "field": "key2.subkey",
          "query": {
            "match": {
              "key2.subkey.finalKey": "name2"
            }
          }
        }
      }
    }
  }
}

我正在努力思考如何根据上面的伪嵌套结构动态地执行此操作。递归的东西,但我不确定如何制作粗箭头函数。

这是迄今为止我得到的最接近的:

const nestQuery = (chain, value, method="match") =>{
	return q => q.query(method, chain, value)
}

const pathMapping = 'key2.subkey.finalKey';
const fooMapping = pathMapping.split('.').map((part, index, splitPath) =>{
	return splitPath.slice(0, index+1).join('.');
})

const body = bodybuilder();
  fooMapping.reduce((nestedBody, subPath, index, allPaths)=>{
    const next = allPaths[index+1] 
    return nestedBody.query('nested', subPath, 
               nestQuery(next, 'blue'))
  }, body)
  console.log(body.build())
<script src="https://rawgit.com/danpaz/bodybuilder/master/browser/bodybuilder.min.js"></script>

但是当我想要一个嵌套查询时,这会给你三个单独的查询。

【问题讨论】:

    标签: javascript bodybuilder.js


    【解决方案1】:

    您使用reduce 的直觉确实朝着正确的方向发展。但是,如果您从最里面的查询开始(其参数看起来与其他 query 调用完全不同),反向工作,这将更容易。这样,您就可以将之前构建的回调包装到另一个回调函数中,从内到外:

    function buildQuery(path, value) {
        // Build one part less, as the last one needs a different query syntax anyway
        //  ... and we have its value already in `path`:
        const keys = path.split('.').slice(0, -1).map((part, index, splitPath) => {
            return splitPath.slice(0, index+1).join('.');
        });
    
        // Use reduceRight to build the query from the inside out.
        const f = keys.reduceRight( (f, key) => {
            return q => q.query("nested", "path", key, f); // f is result of previous iteration
        }, q => q.query("match", path, value)); // Initial value is the innermost query
    
        return f(bodybuilder()).build();
    }    
    
    // Demo
    console.log(buildQuery("key2.subkey.finalKey", "name2"));
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    <script src="https://rawgit.com/danpaz/bodybuilder/master/browser/bodybuilder.min.js"></script>

    【讨论】:

      猜你喜欢
      • 2018-01-03
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 2015-09-24
      • 2023-01-10
      • 2018-09-23
      • 1970-01-01
      • 2017-06-11
      相关资源
      最近更新 更多