Skip to content

Commit

Permalink
add queryFieldNames field in Doc Level Queries (opensearch-project#582)…
Browse files Browse the repository at this point in the history
… (opensearch-project#597)

---------

(cherry picked from commit 75925dc)

Signed-off-by: Surya Sashank Nistala <[email protected]>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

# Conflicts:
#	src/test/kotlin/org/opensearch/commons/alerting/model/XContentTests.kt
  • Loading branch information
goyamegh committed Mar 15, 2024
1 parent 8b18b01 commit 7beca26
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ import java.util.UUID
data class DocLevelQuery(
val id: String = UUID.randomUUID().toString(),
val name: String,
val fields: List<String>,
val query: String,
val tags: List<String> = mutableListOf()
val tags: List<String> = mutableListOf(),
val queryFieldNames: List<String> = mutableListOf()
) : BaseModel {

init {
Expand All @@ -30,42 +32,52 @@ data class DocLevelQuery(
constructor(sin: StreamInput) : this(
sin.readString(), // id
sin.readString(), // name
sin.readStringList(), // fields
sin.readString(), // query
sin.readStringList() // tags
sin.readStringList(), // tags,
sin.readStringList() // fieldsBeingQueried
)

fun asTemplateArg(): Map<String, Any> {
return mapOf(
QUERY_ID_FIELD to id,
NAME_FIELD to name,
FIELDS_FIELD to fields,
QUERY_FIELD to query,
TAGS_FIELD to tags
TAGS_FIELD to tags,
QUERY_FIELD_NAMES_FIELD to queryFieldNames
)
}

@Throws(IOException::class)
override fun writeTo(out: StreamOutput) {
out.writeString(id)
out.writeString(name)
out.writeStringCollection(fields)
out.writeString(query)
out.writeStringCollection(tags)
out.writeStringCollection(queryFieldNames)
}

override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder {
builder.startObject()
.field(QUERY_ID_FIELD, id)
.field(NAME_FIELD, name)
.field(FIELDS_FIELD, fields.toTypedArray())
.field(QUERY_FIELD, query)
.field(TAGS_FIELD, tags.toTypedArray())
.field(QUERY_FIELD_NAMES_FIELD, queryFieldNames.toTypedArray())
.endObject()
return builder
}

companion object {
const val QUERY_ID_FIELD = "id"
const val NAME_FIELD = "name"
const val FIELDS_FIELD = "fields"
const val QUERY_FIELD = "query"
const val TAGS_FIELD = "tags"
const val QUERY_FIELD_NAMES_FIELD = "query_field_names"
const val NO_ID = ""
val INVALID_CHARACTERS: List<String> = listOf(" ", "[", "]", "{", "}", "(", ")")

Expand All @@ -76,6 +88,8 @@ data class DocLevelQuery(
lateinit var query: String
lateinit var name: String
val tags: MutableList<String> = mutableListOf()
val fields: MutableList<String> = mutableListOf()
val queryFieldNames: MutableList<String> = mutableListOf()

XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp)
while (xcp.nextToken() != XContentParser.Token.END_OBJECT) {
Expand All @@ -88,6 +102,7 @@ data class DocLevelQuery(
name = xcp.text()
validateQuery(name)
}

QUERY_FIELD -> query = xcp.text()
TAGS_FIELD -> {
XContentParserUtils.ensureExpectedToken(
Expand All @@ -101,14 +116,40 @@ data class DocLevelQuery(
tags.add(tag)
}
}

FIELDS_FIELD -> {
XContentParserUtils.ensureExpectedToken(
XContentParser.Token.START_ARRAY,
xcp.currentToken(),
xcp
)
while (xcp.nextToken() != XContentParser.Token.END_ARRAY) {
val field = xcp.text()
fields.add(field)
}
}

QUERY_FIELD_NAMES_FIELD -> {
XContentParserUtils.ensureExpectedToken(
XContentParser.Token.START_ARRAY,
xcp.currentToken(),
xcp
)
while (xcp.nextToken() != XContentParser.Token.END_ARRAY) {
val field = xcp.text()
queryFieldNames.add(field)
}
}
}
}

return DocLevelQuery(
id = id,
name = name,
fields = fields,
query = query,
tags = tags
tags = tags,
queryFieldNames = queryFieldNames
)
}

Expand All @@ -129,4 +170,20 @@ data class DocLevelQuery(
}
}
}

// constructor for java plugins' convenience to optionally avoid passing empty list for 'fieldsBeingQueried' field
constructor(
id: String,
name: String,
fields: MutableList<String>,
query: String,
tags: MutableList<String>
) : this(
id = id,
name = name,
fields = fields,
query = query,
tags = tags,
queryFieldNames = emptyList()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@ package org.opensearch.commons.alerting.model
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.opensearch.common.io.stream.BytesStreamOutput
import org.opensearch.common.io.stream.StreamInput
import org.opensearch.commons.alerting.model.action.Action
import org.opensearch.commons.alerting.model.action.ActionExecutionPolicy
import org.opensearch.commons.alerting.model.action.Throttle
import org.opensearch.commons.alerting.randomAction
import org.opensearch.commons.alerting.randomActionExecutionPolicy
import org.opensearch.commons.alerting.randomBucketLevelTrigger
import org.opensearch.commons.alerting.randomChainedAlertTrigger
import org.opensearch.commons.alerting.randomDocLevelQuery
import org.opensearch.commons.alerting.randomDocumentLevelTrigger
import org.opensearch.commons.alerting.randomQueryLevelMonitor
import org.opensearch.commons.alerting.randomQueryLevelTrigger
import org.opensearch.commons.alerting.randomThrottle
import org.opensearch.commons.alerting.randomUser
import org.opensearch.commons.alerting.randomUserEmpty
import org.opensearch.commons.authuser.User
import org.opensearch.core.common.io.stream.StreamInput
import org.opensearch.search.builder.SearchSourceBuilder
import kotlin.test.assertTrue

class WriteableTests {

Expand Down Expand Up @@ -111,6 +114,39 @@ class WriteableTests {
Assertions.assertEquals(trigger, newTrigger, "Round tripping DocumentLevelTrigger doesn't work")
}

@Test
fun `test doc-level query as stream`() {
val dlq = randomDocLevelQuery()
val out = BytesStreamOutput()
dlq.writeTo(out)
val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes)
val newDlq = DocLevelQuery.readFrom(sin)
Assertions.assertEquals(dlq, newDlq, "Round tripping DocLevelQuery doesn't work")
assertTrue(newDlq.queryFieldNames.isEmpty())
}

@Test
fun `test doc-level query with query Field Names as stream`() {
val dlq = randomDocLevelQuery().copy(queryFieldNames = listOf("f1", "f2"))
val out = BytesStreamOutput()
dlq.writeTo(out)
val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes)
val newDlq = DocLevelQuery.readFrom(sin)
assertTrue(newDlq.queryFieldNames.contains(dlq.queryFieldNames[0]))
assertTrue(newDlq.queryFieldNames.contains(dlq.queryFieldNames[1]))
Assertions.assertEquals(dlq, newDlq, "Round tripping DocLevelQuery doesn't work")
}

@Test
fun `test chained alert trigger as stream`() {
val trigger = randomChainedAlertTrigger()
val out = BytesStreamOutput()
trigger.writeTo(out)
val sin = StreamInput.wrap(out.bytes().toBytesRef().bytes)
val newTrigger = ChainedAlertTrigger.readFrom(sin)
Assertions.assertEquals(trigger, newTrigger, "Round tripping DocumentLevelTrigger doesn't work")
}

@Test
fun `test searchinput as stream`() {
val input = SearchInput(emptyList(), SearchSourceBuilder())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,27 @@ class XContentTests {
val throttleString = throttle.toXContent(builder(), ToXContent.EMPTY_PARAMS).string()
val wrongThrottleString = throttleString.replace("MINUTES", "wrongunit")

assertFailsWith<IllegalArgumentException>("Only support MINUTES throttle unit") { Throttle.parse(parser(wrongThrottleString)) }
assertFailsWith<IllegalArgumentException>("Only support MINUTES throttle unit") {
Throttle.parse(
parser(
wrongThrottleString
)
)
}
}

@Test
fun `test throttle parsing with negative value`() {
val throttle = randomThrottle().copy(value = -1)
val throttleString = throttle.toXContent(builder(), ToXContent.EMPTY_PARAMS).string()

assertFailsWith<IllegalArgumentException>("Can only set positive throttle period") { Throttle.parse(parser(throttleString)) }
assertFailsWith<IllegalArgumentException>("Can only set positive throttle period") {
Throttle.parse(
parser(
throttleString
)
)
}
}

fun `test query-level monitor parsing`() {
Expand Down Expand Up @@ -131,7 +143,13 @@ class XContentTests {
}
""".trimIndent()

assertFailsWith<IllegalArgumentException>("Monitor name is null") { Monitor.parse(parser(monitorStringWithoutName)) }
assertFailsWith<IllegalArgumentException>("Monitor name is null") {
Monitor.parse(
parser(
monitorStringWithoutName
)
)
}
}

@Test
Expand Down

0 comments on commit 7beca26

Please sign in to comment.