diff --git a/doctests/query-agg.js b/doctests/query-agg.js new file mode 100644 index 00000000000..7bb974a25f1 --- /dev/null +++ b/doctests/query-agg.js @@ -0,0 +1,139 @@ +// EXAMPLE: query_agg +// HIDE_START +import assert from 'node:assert'; +import fs from 'node:fs'; +import { createClient } from 'redis'; +import { SchemaFieldTypes, AggregateSteps, AggregateGroupByReducers } from '@redis/search'; + +const client = createClient(); + +await client.connect().catch(console.error); + +// create index +await client.ft.create('idx:bicycle', { + '$.condition': { + type: SchemaFieldTypes.TAG, + AS: 'condition' + }, + '$.price': { + type: SchemaFieldTypes.NUMERIC, + AS: 'price' + } +}, { + ON: 'JSON', + PREFIX: 'bicycle:' +}) + +// load data +const bicycles = JSON.parse(fs.readFileSync('data/query_em.json', 'utf8')); + +await Promise.all( + bicycles.map((bicycle, bid) => { + return client.json.set(`bicycle:${bid}`, '$', bicycle); + }) +); +// HIDE_END + +// STEP_START agg1 +const res1 = await client.ft.aggregate('idx:bicycle', '@condition:{new}', { + LOAD: ['__key', 'price'], + APPLY: { + expression: '@price - (@price * 0.1)', + AS: 'discounted' + } +}); + +console.log(res1.results.length); // >>> 5 +console.log(res1.results); // >>> +//[ +// [Object: null prototype] { __key: 'bicycle:0', price: '270' }, +// [Object: null prototype] { __key: 'bicycle:5', price: '810' }, +// [Object: null prototype] { __key: 'bicycle:6', price: '2300' }, +// [Object: null prototype] { __key: 'bicycle:7', price: '430' }, +// [Object: null prototype] { __key: 'bicycle:8', price: '1200' } +//] +// REMOVE_START +assert.strictEqual(res1.results.length, 5); +// REMOVE_END +// STEP_END + +// STEP_START agg2 +const res2 = await client.ft.aggregate('idx:bicycle', '*', { + LOAD: ['@price'], + STEPS: [{ + type: AggregateSteps.APPLY, + expression: '@price<1000', + AS: 'price_category' + },{ + type: AggregateSteps.GROUPBY, + properties: '@condition', + REDUCE:[{ + type: AggregateGroupByReducers.SUM, + property: '@price_category', + AS: 'num_affordable' + }] + }] +}); +console.log(res2.results.length); // >>> 3 +console.log(res2.results); // >>> +//[[Object: null prototype] { condition: 'refurbished', num_affordable: '1' }, +// [Object: null prototype] { condition: 'used', num_affordable: '1' }, +// [Object: null prototype] { condition: 'new', num_affordable: '3' } +//] +// REMOVE_START +assert.strictEqual(res2.results.length, 3); +// REMOVE_END +// STEP_END + +// STEP_START agg3 +const res3 = await client.ft.aggregate('idx:bicycle', '*', { + STEPS: [{ + type: AggregateSteps.APPLY, + expression: "'bicycle'", + AS: 'type' + }, { + type: AggregateSteps.GROUPBY, + properties: '@type', + REDUCE: [{ + type: AggregateGroupByReducers.COUNT, + property: null, + AS: 'num_total' + }] + }] +}); +console.log(res3.results.length); // >>> 1 +console.log(res3.results); // >>> +//[ [Object: null prototype] { type: 'bicycle', num_total: '10' } ] +// REMOVE_START +assert.strictEqual(res3.results.length, 1); +// REMOVE_END +// STEP_END + +// STEP_START agg4 +const res4 = await client.ft.aggregate('idx:bicycle', '*', { + LOAD: ['__key'], + STEPS: [{ + type: AggregateSteps.GROUPBY, + properties: '@condition', + REDUCE: [{ + type: AggregateGroupByReducers.TOLIST, + property: '__key', + AS: 'bicycles' + }] + }] +}); +console.log(res4.results.length); // >>> 3 +console.log(res4.results); // >>> +//[[Object: null prototype] {condition: 'refurbished', bicycles: [ 'bicycle:9' ]}, +// [Object: null prototype] {condition: 'used', bicycles: [ 'bicycle:1', 'bicycle:2', 'bicycle:3', 'bicycle:4' ]}, +// [Object: null prototype] {condition: 'new', bicycles: [ 'bicycle:5', 'bicycle:6', 'bicycle:7', 'bicycle:0', 'bicycle:8' ]}] +// REMOVE_START +assert.strictEqual(res4.results.length, 3); +// REMOVE_END +// STEP_END + +// REMOVE_START +// destroy index and data +await client.ft.dropIndex('idx:bicycle', { DD: true }); +await client.disconnect(); +// REMOVE_END