Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(query-generation): add support for $sort INTELLIJ-196 #131

Merged
merged 1 commit into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ MongoDB plugin for IntelliJ IDEA.
## [Unreleased]

### Added
* [INTELLIJ-196](https://jira.mongodb.org/browse/INTELLIJ-196) Add support for $sort when generating the query into DataGrip.
* [INTELLIJ-195](https://jira.mongodb.org/browse/INTELLIJ-195) Add support for $unwind when generating the query into DataGrip.
* [INTELLIJ-194](https://jira.mongodb.org/browse/INTELLIJ-194) Add support for $addFields when generating the query into DataGrip.
* [INTELLIJ-193](https://jira.mongodb.org/browse/INTELLIJ-193) Add support for generating aggregates with $match and $project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fun <S> MongoshBackend.emitAggregateBody(node: Node<S>, queryContext: QueryConte
Name.PROJECT -> emitProjectStage(stage)
Name.ADD_FIELDS -> emitAddFieldsStage(stage)
Name.UNWIND -> emitUnwindStage(stage)
Name.SORT -> emitSortStage(stage)
else -> {}
}
emitObjectValueEnd(long = true)
Expand All @@ -60,7 +61,8 @@ private val NON_DESTRUCTIVE_STAGES = setOf(
Name.MATCH,
Name.PROJECT,
Name.ADD_FIELDS,
Name.UNWIND
Name.UNWIND,
Name.SORT,
)

private fun <S> Node<S>.isNotDestructive(): Boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mongodb.jbplugin.dialects.mongosh.aggr

import com.mongodb.jbplugin.dialects.mongosh.backend.MongoshBackend
import com.mongodb.jbplugin.mql.Node
import com.mongodb.jbplugin.mql.components.HasSorts

internal fun <S> MongoshBackend.emitSortStage(node: Node<S>): MongoshBackend {
val sorts = node.component<HasSorts<S>>()?.children ?: emptyList()
val isLongSortChain = sorts.size > 3

emitObjectStart(long = isLongSortChain)
emitObjectKey(registerConstant('$' + "sort"))
emitObjectStart(long = isLongSortChain)
emitAsFieldValueDocument(sorts, isLongSortChain)
emitObjectEnd(long = isLongSortChain)
emitObjectEnd(long = isLongSortChain)

return this
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mongodb.jbplugin.dialects.mongosh.query

import com.mongodb.jbplugin.dialects.mongosh.backend.ContextValue
import com.mongodb.jbplugin.dialects.mongosh.backend.MongoshBackend
import com.mongodb.jbplugin.mql.BsonAny
import com.mongodb.jbplugin.mql.BsonString
Expand All @@ -13,18 +14,28 @@ import com.mongodb.jbplugin.mql.components.HasValueReference
fun <S> MongoshBackend.resolveValueReference(
valueRef: HasValueReference<S>,
fieldRef: HasFieldReference<S>?
) = when (val ref = valueRef.reference) {
is HasValueReference.Constant -> registerConstant(ref.value)
is HasValueReference.Inferred -> registerConstant(ref.value)
is HasValueReference.Runtime -> registerVariable(
(fieldRef?.reference as? FromSchema)?.fieldName ?: "value",
ref.type
)

else -> registerVariable(
"queryField",
BsonAny
)
): ContextValue {
return when (val ref = valueRef.reference) {
is HasValueReference.Computed -> {
val node = ref.type.expression
val fieldRef =
node.component<HasFieldReference<S>>()
?: return registerVariable("queryField", ref.type.baseType)

resolveFieldReference(fieldRef)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this because I realised that we weren't supporting Computed values. This is something that we will need to improve whenever we support Computed values that are more than just a field reference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be interesting because now we can finally see if the root bsonType will be helpful in generating these queries or not. Right now we only take one HasFieldReference component but there could be more :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we leave a todo with a ticket or were you planning to tackle this as part of group?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK for now we are only going to support field names as references, no arbitrary expressions, so I think this is kinda of enough for our use cases. I was thinking that we could rework this method in the future whenever we support more types of expressions. I can create a ticket for this, I think it's good to track it.

}
is HasValueReference.Constant -> registerConstant(ref.value)
is HasValueReference.Inferred -> registerConstant(ref.value)
is HasValueReference.Runtime -> registerVariable(
(fieldRef?.reference as? FromSchema)?.fieldName ?: "value",
ref.type
)

else -> registerVariable(
"queryField",
BsonAny
)
}
}

fun <S> MongoshBackend.resolveFieldReference(fieldRef: HasFieldReference<S>) =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.mongodb.jbplugin.dialects.mongosh.aggr

import com.mongodb.jbplugin.dialects.mongosh.assertGeneratedQuery
import com.mongodb.jbplugin.mql.BsonInt32
import com.mongodb.jbplugin.mql.Node
import com.mongodb.jbplugin.mql.components.HasAggregation
import com.mongodb.jbplugin.mql.components.HasFieldReference
import com.mongodb.jbplugin.mql.components.HasSorts
import com.mongodb.jbplugin.mql.components.HasValueReference
import com.mongodb.jbplugin.mql.components.IsCommand
import com.mongodb.jbplugin.mql.components.Name
import com.mongodb.jbplugin.mql.components.Named
import org.junit.jupiter.api.Test

class SortTest {
@Test
fun `can format a sort stage`() {
assertGeneratedQuery(
"""
var collection = ""
var database = ""

db.getSiblingDB(database).getCollection(collection).aggregate([{"${"$"}sort": {"myField": 1, "myOtherField": -1, }}, ])
""".trimIndent()
) {
Node(
Unit,
listOf(
IsCommand(IsCommand.CommandType.AGGREGATE),
HasAggregation(
listOf(
Node(
Unit,
listOf(
Named(Name.SORT),
HasSorts(
listOf(
Node(
Unit,
listOf(
HasFieldReference(
HasFieldReference.FromSchema(
Unit,
"myField"
)
),
HasValueReference(
HasValueReference.Inferred(
Unit,
1,
BsonInt32
)
)
)
),
Node(
Unit,
listOf(
HasFieldReference(
HasFieldReference.FromSchema(
Unit,
"myOtherField"
)
),
HasValueReference(
HasValueReference.Inferred(
Unit,
-1,
BsonInt32
)
)
)
)
)
)
)
)
)
)
)
)
}
}
}
Loading