From 0d7bfd5f90155f2d16abe655e487d8cb29de6188 Mon Sep 17 00:00:00 2001 From: Jan Prochazka Date: Thu, 17 Mar 2022 10:00:11 +0100 Subject: [PATCH] mongo distinct field values --- .../web/src/datagrid/DataFilterControl.svelte | 5 +- packages/web/src/datagrid/DataGridCore.svelte | 1 + .../web/src/modals/ValueLookupModal.svelte | 95 ++++++++++--------- .../dbgate-plugin-mongo/src/backend/driver.js | 48 ++++++++++ 4 files changed, 102 insertions(+), 47 deletions(-) diff --git a/packages/web/src/datagrid/DataFilterControl.svelte b/packages/web/src/datagrid/DataFilterControl.svelte index d412059a..5468dfc6 100644 --- a/packages/web/src/datagrid/DataFilterControl.svelte +++ b/packages/web/src/datagrid/DataFilterControl.svelte @@ -33,6 +33,7 @@ export let pureName = null; export let schemaName = null; export let columnName = null; + export let uniqueName = null; let value; let isError; @@ -223,7 +224,7 @@ multiselect: true, schemaName, pureName, - columnName, + field: columnName || uniqueName, onConfirm: keys => setFilter(keys.map(x => getFilterValueExpression(x)).join(',')), }); } @@ -271,7 +272,7 @@ - {:else if pureName && columnName} + {:else if (pureName && columnName) || (pureName && uniqueName && driver?.databaseEngineTypes?.includes('document'))} diff --git a/packages/web/src/datagrid/DataGridCore.svelte b/packages/web/src/datagrid/DataGridCore.svelte index ce4bfd48..0a5aa85f 100644 --- a/packages/web/src/datagrid/DataGridCore.svelte +++ b/packages/web/src/datagrid/DataGridCore.svelte @@ -1535,6 +1535,7 @@ onGetReference={value => (domFilterControlsRef.get()[col.uniqueName] = value)} foreignKey={col.foreignKey} columnName={col.uniquePath.length == 1 ? col.uniquePath[0] : null} + uniqueName={col.uniqueName} pureName={col.pureName} schemaName={col.schemaName} {conid} diff --git a/packages/web/src/modals/ValueLookupModal.svelte b/packages/web/src/modals/ValueLookupModal.svelte index e2d4e3b3..8abb3435 100644 --- a/packages/web/src/modals/ValueLookupModal.svelte +++ b/packages/web/src/modals/ValueLookupModal.svelte @@ -14,13 +14,14 @@ import FormTextField from '../forms/FormTextField.svelte'; import _ from 'lodash'; import { apiCall } from '../utility/api'; + import ErrorInfo from '../elements/ErrorInfo.svelte'; export let onConfirm; export let conid; export let database; export let pureName; export let schemaName; - export let columnName; + export let field; export let driver; export let multiselect = false; @@ -41,7 +42,7 @@ search, schemaName, pureName, - field: columnName, + field, }); isLoading = false; @@ -59,7 +60,7 @@ - Choose value from {columnName} + Choose value from {field}
@@ -71,51 +72,55 @@ {/if} {#if !isLoading && rows} -
- { - const { value } = e.detail; - if (multiselect) { - if (checkedKeys.includes(value)) checkedKeys = checkedKeys.filter(x => x != value); - else checkedKeys = [...checkedKeys, value]; - } else { - closeCurrentModal(); - onConfirm(value); - } - }} - columns={[ - multiselect && { - fieldName: 'checked', - header: '', - width: '30px', - slot: 1, - }, - { - fieldName: 'value', - header: 'Value', - formatter: row => (row.value == null ? '(NULL)' : row.value), - }, - ]} - > - { - const value = row['value']; - if (e.target.checked) { - if (!checkedKeys.includes(value)) checkedKeys = [...checkedKeys, value]; - } else { + {#if rows.errorMessage} + + {:else} +
+ { + const { value } = e.detail; + if (multiselect) { if (checkedKeys.includes(value)) checkedKeys = checkedKeys.filter(x => x != value); + else checkedKeys = [...checkedKeys, value]; + } else { + closeCurrentModal(); + onConfirm(value); } - e.stopPropagation(); }} - /> - -
+ columns={[ + multiselect && { + fieldName: 'checked', + header: '', + width: '30px', + slot: 1, + }, + { + fieldName: 'value', + header: 'Value', + formatter: row => (row.value == null ? '(NULL)' : row.value), + }, + ]} + > + { + const value = row['value']; + if (e.target.checked) { + if (!checkedKeys.includes(value)) checkedKeys = [...checkedKeys, value]; + } else { + if (checkedKeys.includes(value)) checkedKeys = checkedKeys.filter(x => x != value); + } + e.stopPropagation(); + }} + /> +
+
+ {/if} {/if} diff --git a/plugins/dbgate-plugin-mongo/src/backend/driver.js b/plugins/dbgate-plugin-mongo/src/backend/driver.js index a35e4c05..2f9c4d29 100644 --- a/plugins/dbgate-plugin-mongo/src/backend/driver.js +++ b/plugins/dbgate-plugin-mongo/src/backend/driver.js @@ -277,6 +277,54 @@ const driver = { const db = pool.db(name); await db.createCollection('collection1'); }, + + async loadFieldValues(pool, name, field, search) { + try { + const collection = pool.__getDatabase().collection(name.pureName); + // console.log('options.condition', JSON.stringify(options.condition, undefined, 2)); + + const pipelineMatch = []; + + if (search) { + const tokens = _.compact(search.split(' ').map((x) => x.trim())); + if (tokens.length > 0) { + pipelineMatch.push({ + $match: { + $and: tokens.map((token) => ({ + [field]: { + $regex: `.*${token}.*`, + $options: 'i', + }, + })), + }, + }); + } + } + + let cursor = await collection.aggregate([ + ...pipelineMatch, + { + $group: { _id: '$' + field }, + }, + { + $sort: { _id: 1 }, + }, + { + $limit: 100, + }, + ]); + const rows = await cursor.toArray(); + return _.uniqBy( + rows.map(transformMongoData).map(({ _id }) => { + if (_.isArray(_id) || _.isPlainObject(_id)) return { value: null }; + return { value: _id }; + }), + (x) => x.value + ); + } catch (err) { + return { errorMessage: err.message }; + } + }, }; module.exports = driver;