比如一段 bool 表达式user_id = 1 and (product_id = 1 and (star_num = 4 or star_num = 5) and banned = 1),写成 SQL 是如下形式:

select * from xxx 
where user_id = 1 and
(
    product_id = 1 and (star_num = 4 or star_num = 5) and banned = 1
)

写成Elasticsearch的 DSL 是如下形式:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "user_id": {
              "query": "1",
              "type": "phrase"
            }
          }
        },
        {
          "match": {
            "product_id": {
              "query": "1",
              "type": "phrase"
            }
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "star_num": {
                    "query": "4",
                    "type": "phrase"
                  }
                }
              },
              {
                "match": {
                  "star_num": {
                    "query": "5",
                    "type": "phrase"
                  }
                }
              }
            ]
          }
        },
        {
          "match": {
            "banned": {
              "query": "1",
              "type": "phrase"
            }
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 1
}

Elasticsearch的 DSL 虽然很好理解,但是手写起来非常费劲。前面提供了基于 SDK 的方式来写,但也不足够灵活。

SQL 的 where 部分就是 boolean expression。这种 bool 表达式被解析后,和Elasticsearch的 DSL 结构长得差不多,所以可以直接将 SQL 转换为 DSL。

SQL 的 where 被 parse 之后的结构和Elasticsearch的 DSL 结构对比:

既然结构上完全一致,逻辑上就可以相互转换。以广度优先对 AST 树进行遍历,然后将二元表达式转换成 json 字符串,再拼装起来就可以了,参考:github.com/cch123/elasticsql

最后编辑: kuteng  文档更新时间: 2022-03-22 19:29   作者:kuteng