Skip to content

Commit 7abc0fa

Browse files
committed
compute nested trees
1 parent 7390c5d commit 7abc0fa

File tree

5 files changed

+184
-159
lines changed

5 files changed

+184
-159
lines changed

es6/sql-bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticQuery.scala

Lines changed: 50 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import app.softnetwork.elastic.sql.query.{
1414
IsNotNullExpr,
1515
IsNullCriteria,
1616
IsNullExpr,
17-
NestedElement
17+
NestedElement,
18+
NestedElements
1819
}
1920
import com.sksamuel.elastic4s.ElasticApi._
2021
import com.sksamuel.elastic4s.FetchSourceContext
@@ -46,80 +47,62 @@ case class ElasticQuery(filter: ElasticFilter) {
4647
.asFilter(boolQuery)
4748
.query(innerHitsNames + innerHitsName.getOrElse(""), boolQuery)
4849

49-
val nestedElements: Seq[NestedElement] = criteria.nestedElements.sortBy(_.level)
50-
51-
val nestedParentsPath
52-
: collection.mutable.Map[String, (NestedElement, Seq[NestedElement])] =
53-
collection.mutable.Map.empty
50+
NestedElements.buildNestedTrees(criteria.nestedElements) match {
51+
case Nil =>
52+
matchAllQuery()
53+
case nestedElements =>
54+
def nestedInner(n: NestedElement): InnerHit = {
55+
var inner = innerHits(n.innerHitsName)
56+
n.size match {
57+
case Some(s) =>
58+
inner = inner.from(0).size(s)
59+
case _ =>
60+
}
61+
if (n.sources.nonEmpty) {
62+
inner = inner.fetchSource(
63+
FetchSourceContext(
64+
fetchSource = true,
65+
includes = n.sources.toArray
66+
)
67+
)
68+
}
69+
inner
70+
}
5471

55-
@tailrec
56-
def getNestedParents(
57-
n: NestedElement,
58-
parents: Seq[NestedElement]
59-
): Seq[NestedElement] = {
60-
n.parent match {
61-
case Some(p) =>
62-
if (!nestedParentsPath.contains(p.path)) {
63-
nestedParentsPath += p.path -> (p, Seq(n))
64-
getNestedParents(p, p +: parents)
72+
def buildNestedQuery(n: NestedElement): Query = {
73+
val children = n.children
74+
if (children.nonEmpty) {
75+
val innerQueries = children.map(buildNestedQuery)
76+
val combinedQuery = if (innerQueries.size == 1) {
77+
innerQueries.head
78+
} else {
79+
must(innerQueries)
80+
}
81+
nestedQuery(
82+
n.path,
83+
combinedQuery
84+
) /*.scoreMode(ScoreMode.None)*/
85+
.inner(
86+
nestedInner(n)
87+
)
6588
} else {
66-
nestedParentsPath += p.path -> (p, nestedParentsPath(p.path)._2 :+ n)
67-
parents
89+
nestedQuery(
90+
n.path,
91+
q
92+
) /*.scoreMode(ScoreMode.None)*/
93+
.inner(
94+
nestedInner(n)
95+
)
6896
}
69-
case _ => parents
70-
}
71-
}
72-
73-
val nestedParents = getNestedParents(nestedElements.last, Seq.empty)
74-
75-
def nestedInner(n: NestedElement): InnerHit = {
76-
var inner = innerHits(n.innerHitsName)
77-
n.size match {
78-
case Some(s) =>
79-
inner = inner.from(0).size(s)
80-
case _ =>
81-
}
82-
if (n.sources.nonEmpty) {
83-
inner = inner.fetchSource(
84-
FetchSourceContext(
85-
fetchSource = true,
86-
includes = n.sources.toArray
87-
)
88-
)
89-
}
90-
inner
91-
}
97+
}
9298

93-
def buildNestedQuery(n: NestedElement): Query = {
94-
val children = nestedParentsPath.get(n.path).map(_._2).getOrElse(Seq.empty)
95-
if (children.nonEmpty) {
96-
val innerQueries = children.map(buildNestedQuery)
97-
val combinedQuery = if (innerQueries.size == 1) {
98-
innerQueries.head
99+
if (nestedElements.size == 1) {
100+
buildNestedQuery(nestedElements.head)
99101
} else {
102+
val innerQueries = nestedElements.map(buildNestedQuery)
100103
must(innerQueries)
101104
}
102-
nestedQuery(
103-
n.path,
104-
combinedQuery
105-
) /*.scoreMode(ScoreMode.None)*/
106-
.inner(
107-
nestedInner(n)
108-
)
109-
} else {
110-
nestedQuery(
111-
n.path,
112-
q
113-
) /*.scoreMode(ScoreMode.None)*/
114-
.inner(
115-
nestedInner(n)
116-
)
117-
}
118105
}
119-
if (nestedParents.nonEmpty)
120-
buildNestedQuery(nestedParents.head)
121-
else
122-
buildNestedQuery(nestedElements.last)
123106
}
124107
case child: ElasticChild =>
125108
import child._

es6/sql-bridge/src/test/scala/app/softnetwork/elastic/sql/SQLQuerySpec.scala

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
9191
|HAVING inner_products.deleted=false AND
9292
| inner_products.upForSale=true AND
9393
| inner_products.stock > 0 AND
94-
| match (inner_products.name) against ("lasagnes") AND
95-
| match (inner_products.description, inner_products.ingredients) against ("lasagnes") AND
94+
| match (
95+
| inner_products.name,
96+
| inner_products.description,
97+
| inner_products.ingredients
98+
| ) against ("lasagnes") AND
9699
| min(inner_products.price) > 5.0 AND
97100
| max(inner_products.price) < 50.0 AND
98101
| inner_products.category <> "coffee"
@@ -229,17 +232,17 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
229232
| }
230233
| },
231234
| {
232-
| "match": {
233-
| "products.name": {
234-
| "query": "lasagnes"
235-
| }
236-
| }
237-
| },
238-
| {
239235
| "bool": {
240236
| "should": [
241237
| {
242238
| "match": {
239+
| "products.name": {
240+
| "query": "lasagnes"
241+
| }
242+
| }
243+
| },
244+
| {
245+
| "match": {
243246
| "products.description": {
244247
| "query": "lasagnes"
245248
| }
@@ -300,7 +303,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
300303
| "max_price": "max_price"
301304
| },
302305
| "script": {
303-
| "source": "1 == 1 && 1 == 1 && 1 == 1 && 1 == 1 && 1 == 1 && params.min_price > 5.0 && params.max_price < 50.0 && 1 == 1"
306+
| "source": "params.min_price > 5.0 && params.max_price < 50.0"
304307
| }
305308
| }
306309
| }
@@ -853,7 +856,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
853856
| "cnt": "cnt"
854857
| },
855858
| "script": {
856-
| "source": "1 == 1 && 1 == 1 && params.cnt > 1"
859+
| "source": "params.cnt > 1"
857860
| }
858861
| }
859862
| }
@@ -1168,7 +1171,7 @@ class SQLQuerySpec extends AnyFlatSpec with Matchers {
11681171
| "cnt": "cnt"
11691172
| },
11701173
| "script": {
1171-
| "source": "1 == 1 && 1 == 1 && params.cnt > 1 && 1 == 1"
1174+
| "source": "params.cnt > 1"
11721175
| }
11731176
| }
11741177
| }

sql/bridge/src/main/scala/app/softnetwork/elastic/sql/bridge/ElasticQuery.scala

Lines changed: 50 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import app.softnetwork.elastic.sql.query.{
1414
IsNotNullExpr,
1515
IsNullCriteria,
1616
IsNullExpr,
17-
NestedElement
17+
NestedElement,
18+
NestedElements
1819
}
1920
import com.sksamuel.elastic4s.ElasticApi._
2021
import com.sksamuel.elastic4s.requests.common.FetchSourceContext
@@ -46,81 +47,62 @@ case class ElasticQuery(filter: ElasticFilter) {
4647
.asFilter(boolQuery)
4748
.query(innerHitsNames + innerHitsName.getOrElse(""), boolQuery)
4849

49-
val nestedElements: Seq[NestedElement] = criteria.nestedElements.sortBy(_.level)
50-
51-
val nestedParentsPath
52-
: collection.mutable.Map[String, (NestedElement, Seq[NestedElement])] =
53-
collection.mutable.Map.empty
50+
NestedElements.buildNestedTrees(criteria.nestedElements) match {
51+
case Nil =>
52+
matchAllQuery()
53+
case nestedElements =>
54+
def nestedInner(n: NestedElement): InnerHit = {
55+
var inner = innerHits(n.innerHitsName)
56+
n.size match {
57+
case Some(s) =>
58+
inner = inner.from(0).size(s)
59+
case _ =>
60+
}
61+
if (n.sources.nonEmpty) {
62+
inner = inner.fetchSource(
63+
FetchSourceContext(
64+
fetchSource = true,
65+
includes = n.sources.toArray
66+
)
67+
)
68+
}
69+
inner
70+
}
5471

55-
@tailrec
56-
def getNestedParents(
57-
n: NestedElement,
58-
parents: Seq[NestedElement]
59-
): Seq[NestedElement] = {
60-
n.parent match {
61-
case Some(p) =>
62-
if (!nestedParentsPath.contains(p.path)) {
63-
nestedParentsPath += p.path -> (p, Seq(n))
64-
getNestedParents(p, p +: parents)
72+
def buildNestedQuery(n: NestedElement): Query = {
73+
val children = n.children
74+
if (children.nonEmpty) {
75+
val innerQueries = children.map(buildNestedQuery)
76+
val combinedQuery = if (innerQueries.size == 1) {
77+
innerQueries.head
78+
} else {
79+
must(innerQueries)
80+
}
81+
nestedQuery(
82+
n.path,
83+
combinedQuery
84+
) /*.scoreMode(ScoreMode.None)*/
85+
.inner(
86+
nestedInner(n)
87+
)
6588
} else {
66-
nestedParentsPath += p.path -> (p, nestedParentsPath(p.path)._2 :+ n)
67-
parents
89+
nestedQuery(
90+
n.path,
91+
q
92+
) /*.scoreMode(ScoreMode.None)*/
93+
.inner(
94+
nestedInner(n)
95+
)
6896
}
69-
case _ => parents
70-
}
71-
}
72-
73-
val nestedParents = getNestedParents(nestedElements.last, Seq.empty)
74-
75-
def nestedInner(n: NestedElement): InnerHit = {
76-
var inner = innerHits(n.innerHitsName)
77-
n.size match {
78-
case Some(s) =>
79-
inner = inner.from(0).size(s)
80-
case _ =>
81-
}
82-
if(n.sources.nonEmpty){
83-
inner =
84-
inner.fetchSource(
85-
FetchSourceContext(
86-
fetchSource = true,
87-
includes = n.sources.toArray
88-
)
89-
)
90-
}
91-
inner
92-
}
97+
}
9398

94-
def buildNestedQuery(n: NestedElement): Query = {
95-
val children = nestedParentsPath.get(n.path).map(_._2).getOrElse(Seq.empty)
96-
if (children.nonEmpty) {
97-
val innerQueries = children.map(buildNestedQuery)
98-
val combinedQuery = if (innerQueries.size == 1) {
99-
innerQueries.head
99+
if(nestedElements.size == 1){
100+
buildNestedQuery(nestedElements.head)
100101
} else {
102+
val innerQueries = nestedElements.map(buildNestedQuery)
101103
must(innerQueries)
102104
}
103-
nestedQuery(
104-
n.path,
105-
combinedQuery
106-
) /*.scoreMode(ScoreMode.None)*/
107-
.inner(
108-
nestedInner(n)
109-
)
110-
} else {
111-
nestedQuery(
112-
n.path,
113-
q
114-
) /*.scoreMode(ScoreMode.None)*/
115-
.inner(
116-
nestedInner(n)
117-
)
118-
}
119105
}
120-
if (nestedParents.nonEmpty)
121-
buildNestedQuery(nestedParents.head)
122-
else
123-
buildNestedQuery(nestedElements.last)
124106
}
125107
case child: ElasticChild =>
126108
import child._

0 commit comments

Comments
 (0)