Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #4457 from prisma/MongoCursorBug
Browse files Browse the repository at this point in the history
Mongo Aggregation Fixes
  • Loading branch information
dpetrick authored Apr 30, 2019
2 parents 509b1fd + d0d622d commit 9e17a01
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ trait AggregationQueryBuilder extends FilterConditionBuilder with ProjectionBuil
selectedFields: SelectedFields,
rowValueOpt: Option[GCValue]): Future[Seq[Document]] = {
aggregationQueryForId(database, model, queryArguments, rowValueOpt).flatMap { ids =>
val inFilter = in("_id", ids.map(GCToBson(_)): _*)
database.getCollection(model.dbName).find(inFilter).projection(projectSelected(selectedFields)).toFuture
val bsonIds = ids.distinct.map(GCToBson(_))
database.getCollection(model.dbName).find(in("_id", bsonIds: _*)).projection(projectSelected(selectedFields)).toFuture.map { seq =>
bsonIds.map(id => seq.find(doc => doc.get("_id").get == id).get) //sort according to ids ordering
}
}
}

Expand Down Expand Up @@ -58,7 +60,7 @@ trait AggregationQueryBuilder extends FilterConditionBuilder with ProjectionBuil
//-------------------------------- Match on Cursor Condition ----------------------------------------
val pipeline = rowValueOpt match {
case None => common
case Some(rowValue) => CursorConditionBuilder.buildCursorCondition(model, queryArguments, rowValue) +: common
case Some(rowValue) => `match`(CursorConditionBuilder.buildCursorCondition(model, queryArguments, rowValue)) +: common
}

database.getCollection(model.dbName).aggregate(pipeline).toFuture.map(_.map(readsId))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,29 +116,16 @@ trait NodeManyQueries extends FilterConditionBuilder with AggregationQueryBuilde

//Fixme this does not use all queryarguments
def countFromModel(model: Model, queryArguments: QueryArguments) = SimpleMongoAction { database =>
// val queryArgFilter = queryArguments match {
// case Some(arg) => arg.filter
// case None => None
// }
//
// val skipAndLimit = LimitClauseHelper.skipAndLimitValues(queryArguments)
//
// val cursorCondition = CursorConditionBuilder.buildCursorCondition(queryArguments)
// We could try passing the other args into countoptions, but not sure about order
// val baseQuery2 = collection.countDocuments(Filters.and(buildConditionForFilter(queryArgFilter), cursorCondition)).toFuture()
//
// val baseQuery: FindObservable[Document] = collection(Filters.and(buildConditionForFilter(queryArgFilter), cursorCondition))
// val queryWithOrder: FindObservable[Document] = OrderByClauseBuilder.queryWithOrder(baseQuery, queryArguments)
// val queryWithSkip: FindObservable[Document] = queryWithOrder.skip(skipAndLimit.skip)
//
// val queryWithLimit = skipAndLimit.limit match {
// case Some(limit) => queryWithSkip.limit(limit)
// case None => queryWithSkip
// }
//
// queryWithLimit.collect().toFuture

database.getCollection(model.dbName).countDocuments(buildConditionForFilter(queryArguments.filter)).toFuture.map(_.toInt)
if (needsAggregation(queryArguments.filter)) {
aggregationQueryForId(database, model, queryArguments).map { x =>
x.length match {
case 0 => 0
case x => x - 1 // we always fetch one more item for the page info we need to subtract that
}
}
} else {
database.getCollection(model.dbName).countDocuments(buildConditionForFilter(queryArguments.filter)).toFuture.map(_.toInt)
}
}

def countFromTable(table: String, filter: Option[Filter]) = SimpleMongoAction { database =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.prisma.api.queries

import com.prisma.api.ApiSpecBase
import com.prisma.api.{ApiSpecBase, TestDataModels}
import com.prisma.shared.schema_dsl.SchemaDsl
import org.scalatest.{FlatSpec, Matchers}
import com.prisma.IgnoreSQLite

class MultiItemConnectionQuerySpec extends FlatSpec with Matchers with ApiSpecBase {

val project = SchemaDsl.fromStringV11() {
"""type Todo {
| id: ID! @id
Expand Down Expand Up @@ -108,4 +110,56 @@ class MultiItemConnectionQuerySpec extends FlatSpec with Matchers with ApiSpecBa
)
.toString should equal("""{"data":{"todoesConnection":{"edges":[{"node":{"title":"Hello World!"}}]}}}""")
}

"the connection query" should "work when using cursors when not on Mongo" taggedAs (IgnoreSQLite) in {
val datamodels = {
val dm1 =
"""type User {
id: ID! @id
name: String
following: [User!]! @relation(name: "UserToFollow", link: INLINE)
followers: [User!]! @relation(name: "UserToFollow")
}"""

val dm2 =
"""type User {
| id: ID! @id
| name: String
| following: [User!]! @relation(name: "UserToFollow", link: TABLE)
| followers: [User!]! @relation(name: "UserToFollow")
|}"""

TestDataModels(mongo = Vector(dm1), sql = Vector(dm2))
}
datamodels.testV11 { project =>
val a = server.query(s"""mutation{createUser(data:{name: "a", followers:{create:[{name:"b"}, {name:"c"}, {name:"x"}]}}){id}}""", project)
val d = server.query(s"""mutation{createUser(data:{name: "d", followers:{create:[{name:"e"}, {name:"f"}, {name:"x"}]}}){id}}""", project)
val g = server.query(s"""mutation{createUser(data:{name: "g", followers:{create:[{name:"h"}, {name:"i"}, {name:"x"}]}}){id}}""", project)
val k = server.query(s"""mutation{createUser(data:{name: "k", followers:{create:[{name:"l"}, {name:"m"}, {name:"x"}]}}){id}}""", project)

val result = server.query(
s"""{
| usersConnection(where: {
| followers_some: {
| name: "x"
| },
| }, first: 2, after: "${a.pathAsString("data.createUser.id")}") {
| aggregate {
| count
| }
| edges {
| node {
| name
| }
| }
| }
|}""".stripMargin,
project
)

result.toString should be("""{"data":{"usersConnection":{"aggregate":{"count":2},"edges":[{"node":{"name":"d"}},{"node":{"name":"g"}}]}}}""")

}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.prisma.api.queries

import com.prisma.api.{ApiSpecBase, TestDataModels}
import org.scalatest.{FlatSpec, Matchers}

class RelationFilterOrderingSpec extends FlatSpec with Matchers with ApiSpecBase {

val datamodels = {
val dm1 = """type Blog {
id: ID! @id
title: String!
score: Int!
labels: [Label!]! @relation(name: "BlogLabels", link: INLINE)
}
type Label {
id: ID! @id
text: String! @unique
}"""

val dm2 = """type Blog {
id: ID! @id
title: String!
score: Int!
labels: [Label!]! @relation(name: "BlogLabels", link: TABLE)
}
type Label {
id: ID! @id
text: String! @unique
}"""

TestDataModels(mongo = Vector(dm1), sql = Vector(dm2))
}

"Using relational filters" should "return items in the specified order" in {
datamodels.testV11 { project =>
server.query(s"""mutation {createLabel(data: {text: "x"}) {text }}""", project)

server.query(s"""mutation {createBlog(data: {title: "blog_1", score: 10,labels: {connect: {text: "x"}}}) {title}}""", project)
server.query(s"""mutation {createBlog(data: {title: "blog_1", score: 20,labels: {connect: {text: "x"}}}) {title}}""", project)
server.query(s"""mutation {createBlog(data: {title: "blog_1", score: 30,labels: {connect: {text: "x"}}}) {title}}""", project)

val res1 = server.query("""query {blogs(first: 2, orderBy: score_DESC) {title, score}}""", project)

res1.toString should be("""{"data":{"blogs":[{"title":"blog_1","score":30},{"title":"blog_1","score":20}]}}""")

val res2 = server.query("""query {blogs (first: 2, orderBy: score_DESC, where:{labels_some: {text: "x"}}) {title, score}}""", project)
res2.toString should be("""{"data":{"blogs":[{"title":"blog_1","score":30},{"title":"blog_1","score":20}]}}""")

}
}
}

0 comments on commit 9e17a01

Please sign in to comment.