@@ -19,9 +19,13 @@ object ElasticQueryCompiler extends Backend[QExpr, ElasticQueryNode, JsonNode] {
1919 case QExpr .Eq (QExpr .Prop (path), QExpr .Constant (s)) => EQN .Term (EQN .Field (path), EQN .Constant (s))
2020 case QExpr .Ne (QExpr .Prop (path), QExpr .Constant (s)) =>
2121 EQN .Bool (mustNot = EQN .Term (EQN .Field (path), EQN .Constant (s)) :: Nil )
22- case QExpr .And (exprs) => EQN .Bool (must = exprs map opt)
23- case QExpr .Or (exprs) => EQN .Bool (should = exprs map opt)
24- case QExpr .Not (expr) => EQN .Bool (mustNot = opt(expr) :: Nil )
22+ case QExpr .Gte (QExpr .Prop (path), QExpr .Constant (s)) => EQN .Range (EQN .Field (path), gte = Some (EQN .Constant (s)))
23+ case QExpr .Lte (QExpr .Prop (path), QExpr .Constant (s)) => EQN .Range (EQN .Field (path), lte = Some (EQN .Constant (s)))
24+ case QExpr .Gt (QExpr .Prop (path), QExpr .Constant (s)) => EQN .Range (EQN .Field (path), gt = Some (EQN .Constant (s)))
25+ case QExpr .Lt (QExpr .Prop (path), QExpr .Constant (s)) => EQN .Range (EQN .Field (path), lt = Some (EQN .Constant (s)))
26+ case QExpr .And (exprs) => EQN .Bool (must = exprs map opt)
27+ case QExpr .Or (exprs) => EQN .Bool (should = exprs map opt)
28+ case QExpr .Not (expr) => EQN .Bool (mustNot = opt(expr) :: Nil )
2529 case QExpr .Exists (QExpr .Prop (path), QExpr .Constant (true )) => EQN .Exists (EQN .Field (path))
2630 case QExpr .Exists (QExpr .Prop (path), QExpr .Constant (false )) =>
2731 EQN .Bool (mustNot = EQN .Exists (EQN .Field (path)) :: Nil )
@@ -49,13 +53,24 @@ object ElasticQueryCompiler extends Backend[QExpr, ElasticQueryNode, JsonNode] {
4953 case EQN .Constant (s : Any ) => s.toString
5054 case EQN .Exists (EQN .Field (path)) =>
5155 s """ { "exists": { "field": " ${path.mkString(" ." )}" }} """
56+ case EQN .Range (EQN .Field (path), gt, gte, lt, lte) =>
57+ val bounds = Seq (
58+ renderKeyMap(""" "gt"""" , gt),
59+ renderKeyMap(""" "gte"""" , gte),
60+ renderKeyMap(""" "lt"""" , lt),
61+ renderKeyMap(""" "lte"""" , lte)
62+ ).flatten
63+ s """ {"range": {" ${path.mkString(" ." )}": { ${bounds.mkString(" ," )}}}} """
5264 case EQN .Field (field) =>
5365 // TODO: adjust error message
5466 report.errorAndAbort(s " There is no filter condition on field ${field.mkString(" ." )}" )
5567 case _ => " AST can't be rendered"
5668 }
5769 }
5870
71+ private def renderKeyMap (key : String , node : Option [ElasticQueryNode ])(using quotes : Quotes ): Option [String ] =
72+ node.map(render(_)).map(v => s """ $key: $v""" )
73+
5974 override def target (optRepr : ElasticQueryNode )(using quotes : Quotes ): Expr [JsonNode ] = {
6075 import quotes .reflect .*
6176
@@ -74,6 +89,19 @@ object ElasticQueryCompiler extends Backend[QExpr, ElasticQueryNode, JsonNode] {
7489 ' { JsonNode .obj(" term" -> JsonNode .obj($ { Expr (path.mkString(" ." )) } -> $ { handleValues(x) })) }
7590 case EQN .Exists (EQN .Field (path)) =>
7691 ' { JsonNode .obj(" exists" -> JsonNode .obj(" field" -> JsonNode .Str ($ { Expr (path.mkString(" ." )) }))) }
92+ case EQN .Range (EQN .Field (path), gt, gte, lt, lte) =>
93+ ' {
94+ JsonNode .obj(
95+ " range" -> JsonNode .obj(
96+ $ { Expr (path.mkString(" ." )) } -> JsonNode .obj(
97+ " gt" -> $ { gt.map(handleValues(_)).getOrElse(' { JsonNode .`null` }) },
98+ " gte" -> $ { gte.map(handleValues(_)).getOrElse(' { JsonNode .`null` }) },
99+ " lt" -> $ { lt.map(handleValues(_)).getOrElse(' { JsonNode .`null` }) },
100+ " lte" -> $ { lte.map(handleValues(_)).getOrElse(' { JsonNode .`null` }) }
101+ )
102+ )
103+ )
104+ }
77105 case _ => report.errorAndAbort(" given node can't be in that position" )
78106 }
79107 }
0 commit comments