使用 Bodybuilder 项目简化前端ES查询


bodybuild 分为4个部分

  • aggregation-builder
  • filter-builder
  • query-builder
  • suggestion-builder

index


通过 build 函数即可生成我们常用的es查询DSL

jsx 复制代码
 build: function build(version) {
      var queries = this.getQuery();  
      var filters = this.getFilter();
      var aggregations = this.getAggregations();
      var suggestions = this.getSuggestions();

      if (version === 'v1') return _buildV1(body, queries, filters, aggregations);

      return _build(body, queries, filters, aggregations, suggestions);
}

从上述代码可以看出, bodybuild 通过获取其四大件即可 build 出一个关于ES查询的DSL脚本

入口文件还提供了以下函数

  • sort 在给定字段上设置排序方向。
  • from 设置from偏移量值,用于对查询进行分页。
  • size 设置size值以返回最大结果。
  • rawOption 在 elasticsearch 主体上设置任意键值。
  • clone 返回bodybuilder的克隆实例
jsx 复制代码
 bodybuilder()
	 .andFilter('term', 'user', 'kimchy')
	 .from(2)
	 .size(3)
	 .sort('timestamp', 'desc')
{
    "from": 2,
    "size": 3,
    "sort": [
        {
            "timestamp": {
                "order": "desc"
            }
        }
    ],
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "user": "kimchy"
                }
            }
        }
    }
}

query


dart 复制代码
/**
 * Add a query clause to the query body.
 *
 * @param  {string}        type    查询类型。
 * @param  {string|Object} field   字段来查询或完成查询子句。
 * @param  {string|Object} value   查询项或内部子句
 * @param  {Object}        options (可选)查询子句的附加选项。
 * @param  {Function}      [nest]  (可选)用于将子过滤器定义为子过滤器的函数。这必须是最后一个参数。
 *
 * @return {bodybuilder} Builder.
 */
  • type 第一个参数为请求类型
  • field 需要查询的字段
  • value 匹配的值
jsx 复制代码
bodybuilder().query('**match_all**').build()
{
    "query": {
        "**match_all**": {
        
        }
    }
}
jsx 复制代码
bodybuilder().query('**match_all**', { boost: 1.2 }).build())
{
    "query": {
        "**match_all**": {
            "boost": 1.2
        }
    }
}
jsx 复制代码
bodybuilder().query('**match**', 'message', 'this is a test').build())
{
    "query": {
        "**match**": {
            "message": "this is a test"
        }
    }
}
jsx 复制代码
bodybuilder().query('**terms**', 'user', ['kimchy', 'elastic']).build())
{
    "query": {
        "**terms**": {
            "user": [
                "kimchy",
                "elastic"
            ]
        }
    }
}

上述三个查询 type 、field、value 结合即可完成简单的搜索查询

options 和 nest

jsx 复制代码
 bodybuilder()
 .query(
		 'nested', 
		 { path: 'obj1', score_mode: 'avg' }, 
     (q) => {
		     return q.query('match', 'obj1.name', 'blue')
									.query('range', 'obj1.count', { gt: 5 })
     })
 .build()   
      
// # ES DSL
{
    "query": {
        "nested": {
            "path": "obj1",
            "score_mode": "avg",
            "query": {
                "bool": {
                    "must": [
                        {
                            "match": {
                                "obj1.name": "blue"
                            }
                        },
                        {
                            "range": {
                                "obj1.count": {
                                    "gt": 5
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
}

aggregation


dart 复制代码
/**
 * 向查询主体添加聚合子句。
 *
 * @param  {string|Object} type      聚合类型的名称,如"sum"或"terms"。
 * @param  {string}        field     要聚合的字段的名称。
 * @param  {Object}        [options] (可选)要包含在聚合中的其他选项。
 *                         [options._meta] 将元数据与单个聚合关联起来
 *                         [options._name ] 另一种将自定义名称传递给聚合的方法。
 * @param  {string}        [name]    (可选) 聚合的自定义名称,默认为 `agg_<type>_<field>`.
 * @param  {Function}      [nest]    (可选) 用于将子聚合定义为子聚合的函数。这必须是最后一个参数。
 *
 * @return {bodybuilder} Builder.
 *
 */

这种格式为聚合语句

下面case为type 和 filed的使用

jsx 复制代码
bodybuilder().aggregation('max', 'price').build()
{
	"aggs":{
		"agg_max_price":{
			"max":{
				"field":"price"
			}
		}
	}
}

要包含在聚合中的其他选项。

jsx 复制代码
 bodybuilder()
    .aggregation('max', 'price', { percents: [95, 99, 98] })
    .build()
{
    "aggs": {
        "agg_max_price": {
            "max": {
                "field": "price",
                "percents": [
                    95,
                    99,
                    98
                ]
            }
        }
    }
}
jsx 复制代码
 bodybuilder()
     .aggregation('max', 'price', {
				format: 'MM-yyy',
				ranges: [{ to: 'new-10M/M' }, { from: 'now-10M/M' }]
     })
.build()

// # es
{
    "aggs": {
        "agg_max_price": {
            "max": {
                "field": "price",
                "format": "MM-yyy",
                "ranges": [
                    {
                        "to": "new-10M/M"
                    },
                    {
                        "from": "now-10M/M"
                    }
                ]
            }
        }
    }
}

嵌套aggs

在已经聚合的数据嵌套聚合查询

jsx 复制代码
 bodybuilder()
           .aggregation(
              'max',
              'price',
              {
                format: 'MM-yyy',
                ranges: [{ to: 'new-10M/M' }, { from: 'now-10M/M' }]
              },
              (a) => {
                return a.aggregation('paths', 'text', 'keywords')
              }
            )
            .build()
{
    "aggs": {
        "agg_max_price": {
            "max": {
                "field": "price",
                "format": "MM-yyy",
                "ranges": [
                    {
                        "to": "new-10M/M"
                    },
                    {
                        "from": "now-10M/M"
                    }
                ]
            },
            "aggs": {
                "keywords": {
                    "paths": {
                        "field": "text"
                    }
                }
            }
        }
    }
}

聚合的自定义名称,默认为 agg_<type>_<field>.

jsx 复制代码
bodybuilder()
	.aggregation(
			'max',
			'price',
			{
				_meta: { color: 'blue' }
      },
      'titles'
   )
.build()
{
    "aggs": {
        "titles": {
            "max": {
                "field": "price"
            },
            "meta": {
                "color": "blue"
            }
        }
    }
}

filter-builder


jsx 复制代码
/**
  * 向查询主体添加筛选子句。
  *
  * @param  {string}        type    过滤器类型。
  * @param  {string|Object} field   字段或完成过滤子句。
  * @param  {string|Object} value   过滤项或内部子句。
  * @param  {Object}        options (可选)过滤器子句的附加选项。
  * @param  {Function}      [nest]   (可选)用于将子过滤器定义为子过滤器的函数。这必须是最后一个参数。
  * @return {bodybuilder} Builder.
  *
  */

filter-builder包含几个常规函数分别对应 filter , andFilter, addFilter , orFilter, notFilter 这些函数和 filter 传参一致,notFilterorFilter 比较特殊

must_not 对应 notFilter

should 对应 orFilter

过滤一个简单参数

dart 复制代码
# bodybuilder().filter('term', 'user', 'kimchy').build())
{
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "user": "kimchy"
                }
            }
        }
    }
}
# bodybuilder().**orFilter**('term', 'user', 'kimchy').build())
{ 
    "query": {
        "bool": {
            "filter": {
                **"bool": {
                    "should": [
                        {
                            "term": {
                                "user": "kimchy"
                            }
                        }
                    ]
                }**
            }
        }
    }
}
# bodybuilder().**notFilter**('term', 'user', 'kimchy').build())
{
    "query": {
        "bool": {
            "filter": {
                **"bool": {
                    "must_not": [
                        {
                            "term": {
                                "user": "kimchy"
                            }
                        }
                    ]
                }**
            }
        }
    }
}

定义子过滤器

dart 复制代码
 filter('nested', { path: 'obj1', mode: 'avg' }, (f) => {
		return f.filter('math', 'obj1.name', 'yellow')
 })
            
{
    "query": {
        "bool": {
            "filter": {
                "nested": {
                    "path": "obj1",
                    "mode": "avg",
                    "filter": {
                        "math": {
                            "obj1.name": "yellow"
                        }
                    }
                }
            }
        }
    }
}

 filter('nested', { path: 'obj1', mode: 'avg' }, (f) => {
		return f.filter('math', 'obj1.name', 'yellow')
						.filter('range', 'obj1.count', { gt: 5 })
 })
{
    "query": {
        "bool": {
            "filter": {
                "nested": {
                    "path": "obj1",
                    "mode": "avg",
                    "filter": {
                        "bool": {
                            "must": [
                                {
                                    "math": {
                                        "obj1.name": "yellow"
                                    }
                                },
                                {
                                    "range": {
                                        "obj1.count": {
                                            "gt": 5
                                        }
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
}
相关推荐
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
(⊙o⊙)~哦4 小时前
JavaScript substring() 方法
前端
无心使然云中漫步5 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者5 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_5 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
麒麟而非淇淋6 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120536 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢6 小时前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写8 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js
史努比.8 小时前
redis群集三种模式:主从复制、哨兵、集群
前端·bootstrap·html