mirror of
https://github.com/garraflavatra/rolens.git
synced 2025-01-18 13:07:58 +00:00
Aggregation
This commit is contained in:
parent
715519b06d
commit
1b2315b0b0
@ -54,6 +54,10 @@
|
||||
}
|
||||
summary::before {
|
||||
content: '';
|
||||
display: none;
|
||||
}
|
||||
summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
summary :global(svg) {
|
||||
width: 14px;
|
||||
|
4
frontend/src/components/icon.svelte
vendored
4
frontend/src/components/icon.svelte
vendored
@ -87,5 +87,9 @@
|
||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/>
|
||||
{:else if name === 'save'}
|
||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><path d="M17 21v-8H7v8M7 3v5h8"/>
|
||||
{:else if name === 're'}
|
||||
<path d="m17 1 4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14M7 23l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>
|
||||
{:else if name === 'chart'}
|
||||
<path d="M18 20V10M12 20V4M6 20v-6"/>
|
||||
{/if}
|
||||
</svg>
|
||||
|
92
frontend/src/components/mongo-collation.svelte
Normal file
92
frontend/src/components/mongo-collation.svelte
Normal file
@ -0,0 +1,92 @@
|
||||
<script>
|
||||
import { locales } from '$lib/mongo';
|
||||
|
||||
const defaultCollation = {
|
||||
locale: 'en_US',
|
||||
strength: 3,
|
||||
caseLevel: false,
|
||||
caseFirst: 'off',
|
||||
numericOrdering: false,
|
||||
alternate: 'non-ignorable',
|
||||
maxVariable: 'punct',
|
||||
backwards: false,
|
||||
normalization: false,
|
||||
};
|
||||
|
||||
export let collation = { ...defaultCollation };
|
||||
</script>
|
||||
|
||||
<div class="settinggrid">
|
||||
<label for="collationLocale">Locale</label>
|
||||
<div class="field">
|
||||
<select id="collationLocale" bind:value={collation.locale}>
|
||||
{#each Object.entries(locales) as [value, name]}
|
||||
<option {value}>({value}) {name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="collationStrength">Strength</label>
|
||||
<div class="field">
|
||||
<select id="collationStrength" bind:value={collation.strength}>
|
||||
<option value={1}>(1) Collate base characters only.</option>
|
||||
<option value={2}>(2) Collate up to secondary differences, such as diacritics.</option>
|
||||
<option value={3}>(3) Collate up to tertiary differences, such as case and letter variants.</option>
|
||||
<option value={4}>(4) Limited for specific use case such as processing Japanese text.</option>
|
||||
<option value={5}>(5) Identical Level. Limited for specific use case of tie breaker.</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="collationCaseLevel">Use case level</label>
|
||||
<div class="field">
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="collationCaseLevel" bind:checked={collation.caseLevel} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label for="collationCaseFirst">Case first</label>
|
||||
<div class="field">
|
||||
<select id="collationCaseFirst" bind:value={collation.caseFirst}>
|
||||
<option value="off">(off) Similar to "lower" with slight differences.</option>
|
||||
<option value="upper">(upper) Uppercase sorts before lowercase.</option>
|
||||
<option value="lower">(lower) Lowercase sorts before uppercase.</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="collationNumericOrdering">Numeric ordering</label>
|
||||
<div class="field">
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="collationNumericOrdering" bind:checked={collation.numericOrdering} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label for="collationAlternate">Alternate</label>
|
||||
<div class="field">
|
||||
<select id="collationAlternate" bind:value={collation.alternate}>
|
||||
<option value="non-ignorable">(non-ignorable) Whitespace and punctuation are considered base characters.</option>
|
||||
<option value="shifted">(shifted) Whitespace and punctuation are considered base characters.</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="collationMaxVariable">Max Variable</label>
|
||||
<div class="field">
|
||||
<select id="collationMaxVariable" bind:value={collation.maxVariable}>
|
||||
<option value="punct">(punct) Both whitespace and punctuation are ignorable and not considered base characters.</option>
|
||||
<option value="space">(space) Whitespace is ignorable and not considered to be base characters.</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<label for="collationBackwards">Backwards</label>
|
||||
<div class="field">
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="collationBackwards" bind:checked={collation.backwards} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<label for="collationNormalization">Normalization</label>
|
||||
<div class="field">
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="collationNormalization" bind:checked={collation.normalization} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
@ -18,7 +18,10 @@
|
||||
<ul>
|
||||
{#each tabs as tab (tab.key)}
|
||||
<li class:active={tab.key === selectedKey}>
|
||||
<button class="tab" on:click={() => select(tab.key)}>{tab.title}</button>
|
||||
<button class="tab" on:click={() => select(tab.key)}>
|
||||
{#if tab.icon} <Icon name={tab.icon} /> {/if}
|
||||
{tab.title}
|
||||
</button>
|
||||
{#if tab.closable}
|
||||
<button class="btn-sm" on:click={() => dispatch('closeTab', tab.key)}>
|
||||
<Icon name="x" />
|
||||
|
41
frontend/src/lib/mongo-aggregation-stages.json
Normal file
41
frontend/src/lib/mongo-aggregation-stages.json
Normal file
@ -0,0 +1,41 @@
|
||||
[
|
||||
"$addFields",
|
||||
"$bucket",
|
||||
"$bucketAuto",
|
||||
"$changeStream",
|
||||
"$collStats",
|
||||
"$count",
|
||||
"$currentOp",
|
||||
"$densify",
|
||||
"$documents",
|
||||
"$facet",
|
||||
"$fill",
|
||||
"$geoNear",
|
||||
"$graphLookup",
|
||||
"$group",
|
||||
"$indexStats",
|
||||
"$limit",
|
||||
"$listLocalSessions",
|
||||
"$listSessions",
|
||||
"$lookup",
|
||||
"$match",
|
||||
"$merge",
|
||||
"$out",
|
||||
"$planCacheStats",
|
||||
"$project",
|
||||
"$redact",
|
||||
"$replaceRoot",
|
||||
"$replaceWith",
|
||||
"$sample",
|
||||
"$search",
|
||||
"$searchMeta",
|
||||
"$set",
|
||||
"$setWindowFields",
|
||||
"$shardedDataDistribution",
|
||||
"$skip",
|
||||
"$sort",
|
||||
"$sortByCount",
|
||||
"$unionWith",
|
||||
"$unset",
|
||||
"$unwind"
|
||||
]
|
152
frontend/src/lib/mongo-locales.json
Normal file
152
frontend/src/lib/mongo-locales.json
Normal file
@ -0,0 +1,152 @@
|
||||
{
|
||||
"af": "Afrikaans",
|
||||
"sq": "Albanian",
|
||||
"am": "Amharic",
|
||||
"ar": "Arabic",
|
||||
"ar@collation=compat": "Arabic",
|
||||
"hy": "Armenian",
|
||||
"as": "Assamese",
|
||||
"az": "Azeri",
|
||||
"az@collation=search": "Azeri",
|
||||
"be": "Belarusian",
|
||||
"bn": "Bengali",
|
||||
"bn@collation=traditional": "Bengali",
|
||||
"bs": "Bosnian",
|
||||
"bs@collation=search": "Bosnian",
|
||||
"bs_Cyrl": "Bosnian (Cyrillic)",
|
||||
"bg": "Bulgarian",
|
||||
"my": "Burmese",
|
||||
"ca": "Catalan",
|
||||
"ca@collation=search": "Catalan",
|
||||
"chr": "Cherokee",
|
||||
"zh": "Chinese",
|
||||
"zh@collation=big5han": "Chinese",
|
||||
"zh@collation=gb2312han": "Chinese",
|
||||
"zh@collation=unihan": "Chinese",
|
||||
"zh@collation=zhuyin": "Chinese",
|
||||
"zh_Hant": "Chinese (Traditional)",
|
||||
"hr": "Croatian",
|
||||
"hr@collation=search": "Croatian",
|
||||
"cs": "Czech",
|
||||
"cs@collation=search": "Czech",
|
||||
"da": "Danish",
|
||||
"da@collation=search": "Danish",
|
||||
"nl": "Dutch",
|
||||
"dz": "Dzongkha",
|
||||
"en": "English",
|
||||
"en_US": "English (United States)",
|
||||
"en_US_POSIX": "English (United States, Computer)",
|
||||
"eo": "Esperanto",
|
||||
"et": "Estonian",
|
||||
"ee": "Ewe",
|
||||
"fo": "Faroese",
|
||||
"fil": "Filipino",
|
||||
"fi": "Finnish",
|
||||
"fi@collation=search": "Finnish",
|
||||
"fi@collation=traditional": "Finnish",
|
||||
"fr": "French",
|
||||
"fr_CA": "French (Canada)",
|
||||
"gl": "Galician",
|
||||
"gl@collation=search": "Galician",
|
||||
"ka": "Georgian",
|
||||
"de": "German",
|
||||
"de@collation=eor": "German",
|
||||
"de@collation=phonebook": "German",
|
||||
"de@collation=search": "German",
|
||||
"de_AT": "German (Austria)",
|
||||
"de_AT@collation=phonebook": "German (Austria)",
|
||||
"el": "Greek",
|
||||
"gu": "Gujarati",
|
||||
"ha": "Hausa",
|
||||
"haw": "Hawaiian",
|
||||
"he": "Hebrew",
|
||||
"he@collation=search": "Hebrew",
|
||||
"hi": "Hindi",
|
||||
"hu": "Hungarian",
|
||||
"is": "Icelandic",
|
||||
"is@collation=search": "Icelandic",
|
||||
"ig": "Igbo",
|
||||
"smn": "Inari Sami",
|
||||
"smn@collation=search": "Inari Sami",
|
||||
"id": "Indonesian",
|
||||
"ga": "Irish",
|
||||
"it": "Italian",
|
||||
"ja": "Japanese",
|
||||
"ja@collation=unihan": "Japanese",
|
||||
"kl": "Kalaallisut",
|
||||
"kl@collation=search": "Kalaallisut",
|
||||
"kn": "Kannada",
|
||||
"kn@collation=traditional": "Kannada",
|
||||
"kk": "Kazakh",
|
||||
"km": "Khmer",
|
||||
"kok": "Konkani",
|
||||
"ko": "Korean",
|
||||
"ko@collation=search": "Korean",
|
||||
"ko@collation=searchjl": "Korean",
|
||||
"ko@collation=unihan": "Korean",
|
||||
"ky": "Kyrgyz",
|
||||
"lkt": "Lakota",
|
||||
"lo": "Lao",
|
||||
"lv": "Latvian",
|
||||
"ln": "Lingala",
|
||||
"ln@collation=phonetic": "Lingala",
|
||||
"lt": "Lithuanian",
|
||||
"dsb": "Lower Sorbian",
|
||||
"lb": "Luxembourgish",
|
||||
"mk": "Macedonian",
|
||||
"ms": "Malay",
|
||||
"ml": "Malayalam",
|
||||
"mt": "Maltese",
|
||||
"mr": "Marathi",
|
||||
"mn": "Mongolian",
|
||||
"ne": "Nepali",
|
||||
"se": "Northern Sami",
|
||||
"se@collation=search": "Northern Sami",
|
||||
"nb": "Norwegian Bokmål",
|
||||
"nb@collation=search": "Norwegian Bokmål",
|
||||
"nn": "Norwegian Nynorsk",
|
||||
"nn@collation=search": "Norwegian Nynorsk",
|
||||
"or": "Oriya",
|
||||
"om": "Oromo",
|
||||
"ps": "Pashto",
|
||||
"fa": "Persian",
|
||||
"fa_AF": "Persian (Afghanistan)",
|
||||
"pl": "Polish",
|
||||
"pt": "Portuguese",
|
||||
"pa": "Punjabi",
|
||||
"ro": "Romanian",
|
||||
"ru": "Russian",
|
||||
"sr": "Serbian",
|
||||
"sr_Latn": "Serbian (Latin)",
|
||||
"sr_Latn@collation=search": "Serbian (Latin)",
|
||||
"si": "Sinhala",
|
||||
"si@collation=dictionary": "Sinhala",
|
||||
"sk": "Slovak",
|
||||
"sk@collation=search": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"es": "Spanish",
|
||||
"es@collation=traditional": "Spanish",
|
||||
"es@collation=search": "Spanish",
|
||||
"sw": "Swahili",
|
||||
"sv": "Swedish",
|
||||
"sv@collation=search": "Swedish",
|
||||
"ta": "Tamil",
|
||||
"te": "Telugu",
|
||||
"th": "Thai",
|
||||
"bo": "Tibetan",
|
||||
"to": "Tongan",
|
||||
"tr": "Turkish",
|
||||
"tr@collation=search": "Turkish",
|
||||
"uk": "Ukrainian",
|
||||
"hsb": "Upper Sorbian",
|
||||
"ur": "Urdu",
|
||||
"ug": "Uyghur",
|
||||
"vi": "Vietnamese",
|
||||
"vi@collation=traditional": "Vietnamese",
|
||||
"wae": "Walser",
|
||||
"cy": "Welsh",
|
||||
"yi": "Yiddish",
|
||||
"yi@collation=search": "Yiddish",
|
||||
"yo": "Yoruba",
|
||||
"zu": "Zulu"
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
import { ObjectId } from 'bson';
|
||||
import aggregationStages from './mongo-aggregation-stages.json';
|
||||
import locales from './mongo-locales.json';
|
||||
|
||||
export { aggregationStages, locales };
|
||||
|
||||
// Calculate the min and max values of (un)signed integers with n bits
|
||||
export const intMin = bits => Math.pow(2, bits - 1) * -1;
|
||||
@ -32,3 +36,8 @@ export function canBeObjectId(value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function aggregationStageDocumentationURL(stageName) {
|
||||
const url = `https://www.mongodb.com/docs/manual/reference/operator/aggregation/${stageName.replace('$', '')}/`;
|
||||
return url;
|
||||
}
|
||||
|
127
frontend/src/organisms/connection/collection/aggregate.svelte
Normal file
127
frontend/src/organisms/connection/collection/aggregate.svelte
Normal file
@ -0,0 +1,127 @@
|
||||
<script>
|
||||
import Details from '$components/details.svelte';
|
||||
import Icon from '$components/icon.svelte';
|
||||
import Modal from '$components/modal.svelte';
|
||||
import MongoCollation from '$components/mongo-collation.svelte';
|
||||
import input from '$lib/actions/input';
|
||||
import { aggregationStageDocumentationURL, aggregationStages } from '$lib/mongo';
|
||||
import { Aggregate } from '$wails/go/app/App';
|
||||
import { BrowserOpenURL } from '$wails/runtime/runtime';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
export let collection;
|
||||
|
||||
const options = {};
|
||||
let stages = [];
|
||||
let settingsModalOpen = false;
|
||||
$: invalid = !stages.length || stages.some(stage => {
|
||||
try {
|
||||
JSON.parse(stage.data);
|
||||
return false;
|
||||
}
|
||||
catch {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
function addStage() {
|
||||
stages = [ ...stages, { type: '$match' } ];
|
||||
}
|
||||
|
||||
function deleteStage(index) {
|
||||
stages = [ ...stages.slice(0, index), ...stages.slice(index + 1) ];
|
||||
}
|
||||
|
||||
function openStageDocs(type) {
|
||||
const url = aggregationStageDocumentationURL(type);
|
||||
BrowserOpenURL(url);
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const pipeline = stages.map(stage => ({ [stage.type]: JSON.parse(stage.data) }));
|
||||
await Aggregate(collection.hostKey, collection.dbKey, collection.key, JSON.stringify(pipeline), JSON.stringify(options));
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
if (!stages.length) {
|
||||
stages = [ { type: '$match' } ];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<form class="aggregate" on:submit|preventDefault={run}>
|
||||
<div>
|
||||
{#each stages as stage, index}
|
||||
<Details title="#{index + 1}: {stage.type}" deletable={true} on:delete={() => deleteStage(index)} initiallyOpen>
|
||||
<label class="field">
|
||||
<span class="label">Stage type</span>
|
||||
<select bind:value={stage.type}>
|
||||
{#each aggregationStages as value}
|
||||
<option {value}>{value}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button class="btn secondary" type="button" on:click={() => openStageDocs(stage.type)} title="Open documentation about {stage.type || 'this stage'} on mongodb.org">
|
||||
<Icon name="info" />
|
||||
</button>
|
||||
</label>
|
||||
<label class="field">
|
||||
<textarea bind:value={stage.data} class="code" use:input={{ type: 'json' }}></textarea>
|
||||
</label>
|
||||
</Details>
|
||||
{/each}
|
||||
|
||||
<button class="btn-sm" type="button" on:click={addStage}>
|
||||
<Icon name="+" /> Add stage
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<div>
|
||||
<button class="btn" type="submit" disabled={invalid}>
|
||||
<Icon name="play" /> Run pipeline
|
||||
</button>
|
||||
<button class="btn" type="button" on:click={() => settingsModalOpen = true}>
|
||||
<Icon name="cog" /> Settings
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Modal title="Advanced settings" bind:show={settingsModalOpen}>
|
||||
<div class="settinggrid">
|
||||
<label for="allowDiskUse">Allow disk use</label>
|
||||
<div class="field">
|
||||
<span class="checkbox">
|
||||
<input type="checkbox" id="allowDiskUse" bind:checked={options.allowDiskUse} />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Details title="Set custom collation options">
|
||||
<MongoCollation bind:collation={options.collation} />
|
||||
</Details>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.aggregate {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
grid-template: 1fr auto / 1fr;
|
||||
}
|
||||
|
||||
.settinggrid {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 100px;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
</style>
|
@ -3,6 +3,7 @@
|
||||
import TabBar from '$components/tabbar.svelte';
|
||||
import { EventsOn } from '$wails/runtime/runtime';
|
||||
import { tick } from 'svelte';
|
||||
import Aggregate from './aggregate.svelte';
|
||||
import ViewConfig from './components/viewconfig.svelte';
|
||||
import Find from './find.svelte';
|
||||
import Indexes from './indexes.svelte';
|
||||
@ -46,12 +47,13 @@
|
||||
{#if collection}
|
||||
{#key collection}
|
||||
<TabBar tabs={[
|
||||
{ key: 'stats', title: 'Stats' },
|
||||
{ key: 'find', title: 'Find' },
|
||||
{ key: 'insert', title: 'Insert' },
|
||||
{ key: 'update', title: 'Update' },
|
||||
{ key: 'remove', title: 'Remove' },
|
||||
{ key: 'indexes', title: 'Indexes' },
|
||||
{ key: 'stats', icon: 'chart', title: 'Stats' },
|
||||
{ key: 'find', icon: 'db', title: 'Find' },
|
||||
{ key: 'insert', icon: '+', title: 'Insert' },
|
||||
{ key: 'update', icon: 'edit', title: 'Update' },
|
||||
{ key: 'remove', icon: 'trash', title: 'Remove' },
|
||||
{ key: 'indexes', icon: 'list', title: 'Indexes' },
|
||||
{ key: 'aggregate', icon: 're', title: 'Aggregate' },
|
||||
]} bind:selectedKey={tab} />
|
||||
|
||||
<div class="container">
|
||||
@ -61,6 +63,7 @@
|
||||
{:else if tab === 'update'} <Update {collection} on:performFind={catchQuery} />
|
||||
{:else if tab === 'remove'} <Remove {collection} />
|
||||
{:else if tab === 'indexes'} <Indexes {collection} />
|
||||
{:else if tab === 'aggregate'} <Aggregate {collection} />
|
||||
{/if}
|
||||
</div>
|
||||
{/key}
|
||||
|
@ -179,6 +179,13 @@ code,
|
||||
font-family: Menlo, monospace;
|
||||
}
|
||||
|
||||
.settinggrid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@keyframes flashGreen {
|
||||
0% {
|
||||
color: #0d0;
|
||||
|
2
frontend/wailsjs/go/app/App.d.ts
vendored
2
frontend/wailsjs/go/app/App.d.ts
vendored
@ -7,6 +7,8 @@ import {menu} from '../models';
|
||||
|
||||
export function AddHost(arg1:string):Promise<void>;
|
||||
|
||||
export function Aggregate(arg1:string,arg2:string,arg3:string,arg4:string,arg5:string):Promise<void>;
|
||||
|
||||
export function CreateIndex(arg1:string,arg2:string,arg3:string,arg4:string):Promise<string>;
|
||||
|
||||
export function DropCollection(arg1:string,arg2:string,arg3:string):Promise<boolean>;
|
||||
|
@ -6,6 +6,10 @@ export function AddHost(arg1) {
|
||||
return window['go']['app']['App']['AddHost'](arg1);
|
||||
}
|
||||
|
||||
export function Aggregate(arg1, arg2, arg3, arg4, arg5) {
|
||||
return window['go']['app']['App']['Aggregate'](arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
|
||||
export function CreateIndex(arg1, arg2, arg3, arg4) {
|
||||
return window['go']['app']['App']['CreateIndex'](arg1, arg2, arg3, arg4);
|
||||
}
|
||||
|
70
internal/app/collection_aggregate.go
Normal file
70
internal/app/collection_aggregate.go
Normal file
@ -0,0 +1,70 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func (a *App) Aggregate(hostKey, dbKey, collKey, pipelineJson, settingsJson string) {
|
||||
var settings *options.AggregateOptions
|
||||
if err := json.Unmarshal([]byte(settingsJson), &settings); err != nil {
|
||||
runtime.LogError(a.ctx, "Could not parse aggregation settings:")
|
||||
runtime.LogError(a.ctx, err.Error())
|
||||
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||
Type: runtime.ErrorDialog,
|
||||
Title: "Couldn't parse aggregation settings",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var pipeline mongo.Pipeline
|
||||
if err := bson.UnmarshalExtJSON([]byte(pipelineJson), true, &pipeline); err != nil {
|
||||
runtime.LogWarning(a.ctx, "Could not parse aggregation pipeline:")
|
||||
runtime.LogWarning(a.ctx, err.Error())
|
||||
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||
Type: runtime.ErrorDialog,
|
||||
Title: "Couldn't parse aggregation pipeline",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
client, ctx, close, err := a.connectToHost(hostKey)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer close()
|
||||
|
||||
cursor, err := client.Database(dbKey).Collection(collKey).Aggregate(ctx, pipeline, settings)
|
||||
if err != nil {
|
||||
runtime.LogWarning(a.ctx, "Could not get aggregation cursor:")
|
||||
runtime.LogWarning(a.ctx, err.Error())
|
||||
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||
Type: runtime.ErrorDialog,
|
||||
Title: "Couldn't get aggregation cursor",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var results []bson.M
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
runtime.LogInfo(a.ctx, "Error while running aggregation pipeline:")
|
||||
runtime.LogInfo(a.ctx, err.Error())
|
||||
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
|
||||
Type: runtime.ErrorDialog,
|
||||
Title: "Error while running aggregation pipeline",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(results)
|
||||
}
|
@ -21,7 +21,7 @@ type QueryResult struct {
|
||||
Results []string `json:"results"`
|
||||
}
|
||||
|
||||
func (a *App) FindItems(hostKey, dbKey, collKey string, formJson string) QueryResult {
|
||||
func (a *App) FindItems(hostKey, dbKey, collKey, formJson string) QueryResult {
|
||||
var out QueryResult
|
||||
var form Query
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user