以前の仕事の1つで、似たようなことをしました。クエリ(SQLではありませんが、かなり似ています)を取得し、antlrを使用してmongoクエリに変換しました。
共有するコードはありませんが、考えを共有することはできます:
-
MongoはSQLに準拠していないため、SQL文法を使用することはできません。 JOINとすべての関係代数はどうですか?アグリゲーションフレームワークを使用するmongoではかなりトリッキーなアグリゲーションはどうですか?反対の方向で、mongoの「exists」句に変換されるSQLをどのように生成しますか。このようなものはたくさんあります。小さいものもあれば、大きいものもありますが、最終的には、SQLのサブセット、クエリ言語として使用できるDSL、SQLのように見えるものについて話し合う必要があります。人々はSQLに慣れています。
-
そのことを念頭に置いて、独自の文法を作成する必要があります。そうすれば、Antlrがレクサー/パーサーを生成します。また、ランタイムでのクエリの構文チェックも当然のことです。明らかに正しい形式でない場合、Antlrはクエリを解析できません。一部の文法規則は失敗します。これは、SQLを「現状のまま」とらないもう1つの理由です。
-
これまでのところ、あなたはあなた自身のリスナー/訪問者を作成しました。私の場合、内部状態とすべてを含むクエリのオブジェクト表現を作成することを選択しました。したがって、クエリ
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
タイプのオブジェクトに変換されました:
class Query {
private SelectClause select;
private FromClause from;
private WhereClause where;
private Limit limit;
}
class SelectClause {
private List<String> fields;
}
...
class WhereClause {
Condition root;
}
interface Condition {
...
}
class AndCondition implements Condition { // the same for Not, Or
}
この特定のクエリの場合、次のようになります。
Query q = new Query(new SelectClause(["id", "name"]), new FromClause("employee"), new WhereClause(new AndCondition(new SimpleLeafCondition("age", Operators.GT, 30), new SimpleLeafCondition("department", Operators.EQ, "IT" )), new Limit(30));
次に、クエリでいくつかの最適化を行うことができます(必要に応じてwhere句を埋め込む、たとえば、マルチテナント環境で作業していてテナントごとに異なるコレクションがある場合は「For」部分を操作するなど)。
結局のところ、デザインパターン「インタプリタ」を使用して、クエリオブジェクトを再帰的に解析し、それらを有効なmongoクエリに「変換」することができます。この手順を実行するのに1日ほどかかったことを覚えています(mongo 2 Iでは7年前でした)。推測しますが、それでも)、クエリを表すオブジェクトの正しい構造を考えると、これはそれほど複雑ではないはずです。質問の主な関心事のように見えるので、これを取り上げます。