web-dev-qa-db-ja.com

カスタムDSLクエリのようなSQLをElasticSearchに変換しますか?

私たちは、antlr4を使用して、Mysqlに似た独自のクエリ言語を構築しています。 _where clause_のみを使用することを除いて、つまり、ユーザーは_select/from_ステートメントを入力しません。

文法を作成し、golangでレクサー/パーサー/リスナーを生成することができました。

文法ファイルEsDslQuery.g4の下:

_grammar EsDslQuery;

options {
language = Go;
}

query
   : leftBracket = '(' query rightBracket = ')'                             #bracketExp
   | leftQuery=query op=OR rightQuery=query                                 #orLogicalExp
   | leftQuery=query op=AND rightQuery=query                                #andLogicalExp
   | propertyName=attrPath op=COMPARISON_OPERATOR propertyValue=attrValue   #compareExp
   ;

attrPath
   : ATTRNAME ('.' attrPath)?
   ;

fragment ATTR_NAME_CHAR
   : '-' | '_' | ':' | DIGIT | ALPHA
   ;

fragment DIGIT
   : ('0'..'9')
   ;

fragment ALPHA
   : ( 'A'..'Z' | 'a'..'z' )
   ;

attrValue
   : BOOLEAN           #boolean
   | NULL              #null
   | STRING            #string
   | DOUBLE            #double
   | '-'? INT EXP?     #long
   ;

...
_

クエリ例:color="red" and price=20000 or model="hyundai" and (seats=4 or year=2001)

ElasticSearchは、プラグインを使用したSQLクエリをサポートしています https://github.com/elastic/elasticsearch/tree/master/x-pack/plugin/sql

Javaコードを理解するのに苦労しています。

論理演算子があるので、解析ツリーを取得してESクエリに変換する方法がわかりません。誰かがアイデアを助け/提案できますか?

更新1:対応するESクエリでさらに例を追加しました

クエリ例1:_color="red" AND price=2000_

ESクエリ1:

_{
    "query": {
      "bool": {
        "must": [
          {
            "terms": {
              "color": [
                "red"
              ]
            }
          },
          {
            "terms": {
              "price": [
                2000
              ]
            }
          }
        ]
      }
    },
    "size": 100
  }

_

クエリ例2:color="red" AND price=2000 AND (model="hyundai" OR model="bmw")

ESクエリ2:

_{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "must": {
              "terms": {
                "color": ["red"]
              }
            }
          }
        },
        {
          "bool": {
            "must": {
              "terms": {
                "price": [2000]
              }
            }
          }
        },
        {
          "bool": {
            "should": [
              {
                "term": {
                  "model": "hyundai"
                }
              },
              {
                "term": {
                  "region": "bmw"
                }
              }
            ]
          }
        }
      ]
    }
  },
  "size": 100
}


_

クエリ例3:_color="red" OR color="blue"_

ESクエリ3:

_{
    "query": {
      "bool": {
        "should": [
          {
            "bool": {
              "must": {
                "terms": {
                  "color": ["red"]
                }
              }
            }
          },
          {
            "bool": {
              "must": {
                "terms": {
                    "color": ["blue"]
                }
              }
            }
          }
        ]
      }
    },
    "size": 100
  }

_
8

SQLのようなステートメントを クエリ文字列クエリ に変換することを考えましたか?

_curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
    "query": {
        "query_string" : {
            "query" : "(new york city) OR (big Apple)",
            "default_field" : "content"
        }
    }
}
'
_

ユースケースがcolor="red" and price=20000 or model="hyundai" and (seats=4 or year=2001)のように単純である場合は、上記を使用します。構文はかなり 強力 ですが、ESパーサーがDSLに変換する必要があるため、クエリはネイティブのスペルアウトされたDSLクエリよりも実行が遅くなることが保証されています。

2
joe

Dremioというソフトウェアがあります https://www.dremio.com/

SQLクエリをエラスティック検索クエリに変換できます

https://www.dremio.com/tutorials/unlocking-sql-on-elasticsearch/

2
user1392853