From 0cfcf8a017711d5f928cbb9b7d53ba16d04b3e1a Mon Sep 17 00:00:00 2001 From: Deepak Prabhakara Date: Wed, 17 Jul 2024 15:04:12 +0100 Subject: [PATCH] added target.{id,name,type} to pg index (#1510) * added target.{id,name,type} to pg index * feat: Add target properties to event query parsing and filtering --------- Co-authored-by: ukrocks007 --- .../pg/1721206581.do.more_indexed_events.sql | 7 ++ .../1721206581.undo.more_indexed_events.sql | 1 + src/models/event/filter.ts | 33 +++++++ src/models/event/index.ts | 15 +++ src/test/models/event/filter.ts | 92 +++++++++++++++++++ 5 files changed, 148 insertions(+) create mode 100644 migrations/pg/1721206581.do.more_indexed_events.sql create mode 100644 migrations/pg/1721206581.undo.more_indexed_events.sql diff --git a/migrations/pg/1721206581.do.more_indexed_events.sql b/migrations/pg/1721206581.do.more_indexed_events.sql new file mode 100644 index 000000000..b35324007 --- /dev/null +++ b/migrations/pg/1721206581.do.more_indexed_events.sql @@ -0,0 +1,7 @@ +-- SQL goes here +-- GIN jsonb_path_ops for equality queries +CREATE INDEX target_id_idx ON indexed_events USING GIN ((doc -> 'target' -> 'id') jsonb_path_ops); + +-- expression indexes used for matching (@@) tsquery types +CREATE INDEX target_name_idx ON indexed_events USING GIN (to_tsvector('english', (doc -> 'target' -> 'name'))); +CREATE INDEX target_type_idx ON indexed_events USING GIN (to_tsvector('english', (doc -> 'target' -> 'type'))); diff --git a/migrations/pg/1721206581.undo.more_indexed_events.sql b/migrations/pg/1721206581.undo.more_indexed_events.sql new file mode 100644 index 000000000..1426f0606 --- /dev/null +++ b/migrations/pg/1721206581.undo.more_indexed_events.sql @@ -0,0 +1 @@ +-- SQL goes here \ No newline at end of file diff --git a/src/models/event/filter.ts b/src/models/event/filter.ts index 750e41850..d67de9645 100644 --- a/src/models/event/filter.ts +++ b/src/models/event/filter.ts @@ -150,6 +150,17 @@ export function getFilters(query: ParsedQuery, scope: Scope): Filter[] { filters.push(orJoin(some)); } + if (query.target_id) { + const some = _.map(query.target_id, (id) => { + return { + where: `(doc -> 'target' -> 'id') @> ${nextParam()}`, + values: [quote(id)], + }; + }); + + filters.push(orJoin(some)); + } + if (query.actor_name) { const some = _.map(query.actor_name, (name) => { return { @@ -161,6 +172,28 @@ export function getFilters(query: ParsedQuery, scope: Scope): Filter[] { filters.push(orJoin(some)); } + if (query.target_name) { + const some = _.map(query.target_name, (name) => { + return { + where: `to_tsvector('english', (doc -> 'target' -> 'name')) @@ plainto_tsquery('english', ${nextParam()})`, + values: [name], + }; + }); + + filters.push(orJoin(some)); + } + + if (query.target_type) { + const some = _.map(query.target_type, (typ) => { + return { + where: `to_tsvector('english', (doc -> 'target' -> 'type')) @@ plainto_tsquery('english', ${nextParam()})`, + values: [typ], + }; + }); + + filters.push(orJoin(some)); + } + if (query.description) { filters.push({ where: `to_tsvector('english', (doc -> 'description')) @@ plainto_tsquery('english', ${nextParam()})`, diff --git a/src/models/event/index.ts b/src/models/event/index.ts index 4c9b5d2a5..c8dff0a36 100644 --- a/src/models/event/index.ts +++ b/src/models/event/index.ts @@ -51,6 +51,9 @@ export interface ParsedQuery { location?: string[]; external_id?: string[]; text?: string; + target_id?: string[]; + target_name?: string[]; + target_type?: string[]; } const structuredQueryKeywords = [ @@ -63,6 +66,9 @@ const structuredQueryKeywords = [ "description", "location", "external_id", + "target.id", + "target.name", + "target.type", "fields.*", ]; @@ -114,6 +120,15 @@ export function parseQuery(query: string): ParsedQuery { if (intermediate["actor.name"]) { parsed.actor_name = toArray(intermediate["actor.name"]); } + if (intermediate["target.id"]) { + parsed.target_id = toArray(intermediate["target.id"]); + } + if (intermediate["target.name"]) { + parsed.target_name = toArray(intermediate["target.name"]); + } + if (intermediate["target.type"]) { + parsed.target_type = toArray(intermediate["target.type"]); + } if (intermediate["external_id"]) { parsed.external_id = toArray(intermediate["external_id"]); } diff --git a/src/test/models/event/filter.ts b/src/test/models/event/filter.ts index b339c8e32..fefd5b5aa 100644 --- a/src/test/models/event/filter.ts +++ b/src/test/models/event/filter.ts @@ -11,6 +11,98 @@ const minScope = { }; const tests = [ + { + query: "target.id:'tasks'", + parsed: { + target_id: ["tasks"], + }, + scope: minScope, + filters: [ + { + where: `(doc -> 'target' -> 'id') @> $1`, + values: ['"tasks"'], + }, + { where: "project_id = $2", values: ["proj1"] }, + { where: "environment_id = $3", values: ["env1"] }, + ], + }, + { + query: "target.id:tasks,1", + parsed: { + target_id: ["tasks", "1"], + }, + scope: minScope, + filters: [ + { + where: "((doc -> 'target' -> 'id') @> $1 OR (doc -> 'target' -> 'id') @> $2)", + values: ['"tasks"', '"1"'], + }, + { where: "project_id = $3", values: ["proj1"] }, + { where: "environment_id = $4", values: ["env1"] }, + ], + }, + { + query: "target.name:'tasks'", + parsed: { + target_name: ["tasks"], + }, + scope: minScope, + filters: [ + { + where: "to_tsvector('english', (doc -> 'target' -> 'name')) @@ plainto_tsquery('english', $1)", + values: ["tasks"], + }, + { where: "project_id = $2", values: ["proj1"] }, + { where: "environment_id = $3", values: ["env1"] }, + ], + }, + { + query: "target.name:tasks,100", + parsed: { + target_name: ["tasks", "100"], + }, + scope: minScope, + filters: [ + { + where: + "(to_tsvector('english', (doc -> 'target' -> 'name')) @@ plainto_tsquery('english', $1) OR to_tsvector('english', (doc -> 'target' -> 'name')) @@ plainto_tsquery('english', $2))", + values: ["tasks", "100"], + }, + { where: "project_id = $3", values: ["proj1"] }, + { where: "environment_id = $4", values: ["env1"] }, + ], + }, + { + query: "target.type:'tasks'", + parsed: { + target_type: ["tasks"], + }, + scope: minScope, + filters: [ + { + where: "to_tsvector('english', (doc -> 'target' -> 'type')) @@ plainto_tsquery('english', $1)", + values: ["tasks"], + }, + { where: "project_id = $2", values: ["proj1"] }, + { where: "environment_id = $3", values: ["env1"] }, + ], + }, + { + query: "target.type:tasks,100", + parsed: { + target_type: ["tasks", "100"], + }, + scope: minScope, + filters: [ + { + where: + "(to_tsvector('english', (doc -> 'target' -> 'type')) @@ plainto_tsquery('english', $1) OR to_tsvector('english', (doc -> 'target' -> 'type')) @@ plainto_tsquery('english', $2))", + values: ["tasks", "100"], + }, + { where: "project_id = $3", values: ["proj1"] }, + { where: "environment_id = $4", values: ["env1"] }, + ], + }, { query: "action:foo.get", parsed: {