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 <snistala@amazon.com>
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>
  • Loading branch information
2 people authored and goyamegh committed Mar 13, 2024
1 parent 31322e1 commit 7a61f08
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package org.opensearch.commons.alerting.model

import org.opensearch.common.io.stream.StreamInput
import org.opensearch.common.io.stream.StreamOutput
import org.opensearch.common.xcontent.XContentParserUtils
import org.opensearch.commons.notifications.model.BaseModel
import org.opensearch.core.common.io.stream.StreamInput
import org.opensearch.core.common.io.stream.StreamOutput
import org.opensearch.core.xcontent.ToXContent
import org.opensearch.core.xcontent.XContentBuilder
import org.opensearch.core.xcontent.XContentParser
import org.opensearch.core.xcontent.XContentParserUtils
import java.io.IOException
import java.lang.IllegalArgumentException
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
Loading

0 comments on commit 7a61f08

Please sign in to comment.