sql >> Database >  >> NoSQL >> MongoDB

SQL-query ontleden met behulp van antlr parsetree naar mongo bson-document in Java

In een van mijn vorige banen deed ik iets soortgelijks:ik kreeg een query (geen sql, maar redelijk vergelijkbaar) en vertaalde deze naar mongo-query met antlr.

Ik heb geen code om te delen, maar ik kan mijn gedachten delen:

  1. Mongo is niet SQL-compatibel, dus je kunt niet zomaar een sql-grammatica nemen. Hoe zit het met JOIN's en alle relationele algebra? Hoe zit het met aggregaties die behoorlijk lastig zijn in mongo met hun aggregatieraamwerk? In de tegenovergestelde richting, hoe genereer je SQL die wordt vertaald naar de clausule "bestaat" in mongo. Er zijn veel van dit soort dingen, sommige zijn klein, sommige zijn enorm, maar uiteindelijk moet je het hebben over een soort subset van sql, een of andere DSL die mag worden gebruikt als een querytaal en eruitziet als een sql omdat mensen zijn gewend aan SQL.

  2. Met dat in gedachten moet je je eigen grammatica maken en Antlr zal een lexer/parser voor je genereren. U krijgt ook vanzelfsprekend een syntaxiscontrole van de query in Runtime. Antlr zal de query niet kunnen ontleden als deze niet in een correct formaat is, uiteraard zal een grammaticaregel falen. Dit is nog een reden om SQL niet "as is" te nemen.

  3. So far so good, je hebt je eigen luisteraar/bezoeker aangemaakt. In mijn geval heb ik ervoor gekozen om een ​​objectrepresentatie van de query te maken met interne status en alles. Dus de query

Select id,name 
from employee 
where age > 30 
 and department = 'IT' 
limit 200

Werd vertaald naar objecten van het type:


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

}

Voor deze specifieke vraag is het zoiets als:

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));

Dan is het mogelijk om enkele optimalisaties in de query aan te brengen (zoals het insluiten van waar-clausules indien nodig, of bijvoorbeeld het manipuleren van het "For"-gedeelte als u in een omgeving met meerdere tenants werkt en verschillende verzamelingen voor verschillende tenants hebt).

Je kunt tenslotte met ontwerppatroon "interpreter" gaan en de query-objecten recursief ontleden en ze "vertalen" naar een geldige mongo-query. Ik herinner me dat deze stap me ongeveer 1 dag kostte om te bereiken (het was 7 jaar geleden met mongo 2 I raden, maar toch), gezien de juiste structuur van objecten die de query vertegenwoordigen, zou dit niet zo ingewikkeld moeten zijn. Ik breng dit naar voren, omdat het erop lijkt dat dit je eerste zorg is in de vraag.




  1. com.mongodb.MongoException:niet praten met master en nieuwe pogingen opgebruikt

  2. redis vs hazelcast

  3. Mongodb:$in-operator versus veel enkele zoekopdrachten

  4. MongoDB:update het hele document behalve _id met behulp van C#-stuurprogramma