I et af mine tidligere job lavede jeg noget lignende:fik en forespørgsel (ikke en sql, men ret ens) og oversatte den til mongo-forespørgsel med antlr.
Jeg har ikke en kode at dele, men jeg kan dele mine tanker:
-
Mongo er ikke SQL-kompatibel, så du kan ikke bare tage en sql-grammatik. Hvad med JOINs og al den relationelle algebra? Hvad med aggregeringer, der er ret vanskelige i mongo med deres aggregeringsramme? I den modsatte retning, hvordan genererer du SQL, der bliver oversat til "eksisterer"-klausul på mongo. Der er mange ting som dette, nogle er små, nogle er enorme, men bundlinjen må du tale om en form for delmængde af sql, noget DSL, der må bruges som et forespørgselssprog og ligner "sql" fordi folk er vant til SQL.
-
Med det i tankerne bør du oprette din egen grammatik, og Antlr vil generere en lexer/parser til dig. Du får også for givet et syntakstjek af forespørgslen i Runtime. Antlr vil ikke være i stand til at analysere forespørgslen, hvis den ikke er i det korrekte format, selvfølgelig vil en eller anden grammatikregel mislykkes. Dette er en anden grund til ikke at tage SQL "som den er".
-
Så langt så godt, du har oprettet din egen lytter / besøgende. I mit tilfælde har jeg valgt at oprette en objektrepræsentation af forespørgslen med intern tilstand og det hele. Så forespørgslen
Select id,name
from employee
where age > 30
and department = 'IT'
limit 200
Blev oversat til objekter af typen:
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
}
For denne særlige forespørgsel er det noget i retning af:
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));
Så er det muligt at lave nogle optimeringer i forespørgslen (såsom indlejring af hvor-klausuler, hvis du har brug for det, eller for eksempel at manipulere "For"-delen, hvis du arbejder med et miljø med flere lejere og har forskellige samlinger for forskellige lejere).
Når alt kommer til alt kan du gå med designmønster "tolk" og rekursivt parse forespørgselsobjekterne og "oversætte" dem til gyldig mongo-forespørgsel. Jeg kan huske, at dette trin tog mig noget i retning af 1 dag at udføre (det var 7 år siden med mongo 2 I gæt, men stadig), givet den korrekte struktur af objekter, der repræsenterer forespørgslen, så dette burde ikke være så kompliceret. Jeg bringer dette op, fordi det ser ud til, at det er din primære bekymring i spørgsmålet.