vazco / sparrowql

Declarative MongoDB aggregations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SparrowQL computed function example

ralphievolt opened this issue · comments

Based on the blog here
https://medium.com/vazco/dynamic-aggregations-with-sparrowql-dfeb133821e7

There’s also computed, which is an advanced feature, designed to handle a $group phase.

however the feature cannot be seen in the manual to creat the $group operators

Indeed, it's not yet documented. Again, here's the tests we'll analyze [1] and [2].

In general, computed has two modes: mapper (used to make $project phases) and non-mapper (default, to make $group phases). Let's start with mapper (2):

const pipeline = build({
    computed: {
        mapper: {
            mapper: true,
            required: [`${collectionA.collectionName}.i`, `${collectionA.collectionName}.n`],
            result: ['y'],
            perform: relative => ({
                _id: relative(`${collectionA.collectionName}._id`, true),
                y: relative(`${collectionA.collectionName}.x`, true)
            })
        }
    },
    sort: {[makeComputed('mapper.y')]: 1},
    start: collectionA.collectionName
});

How it works:

  • mapper: true states, that $project phase will be used,
  • required defines a list of fields, which are needed to compute this phase,
  • result lists all outputs, which may be used later in query, sort, etc.,
  • perform is a function, which has to return the body of given phase (here: projection),
  • relative(name, isPath) function is useful to make sure, that the perform works for each start collection
  • isPath parameter prefixes returned path with $, which is sometimes needed, for example in $ifNull or at the top level in projection phase.

Now the non-mapper (1):

const pipeline = build({
    computed: {
        stats: {
            required: [`${collectionA.collectionName}.i`, `${collectionA.collectionName}.n`],
            result: ['sum'],
            perform: relative => ({
                _id: relative(`${collectionA.collectionName}.i`, true),
                sum: {$sum: '$n'}
            })
        }
    },
    sort: {[makeComputed('stats.sum')]: 1},
    query: {[`${collectionA.collectionName}.i`]: {$ne: 'spam'}},
    start: collectionA.collectionName
});

Important difference:

  • no mapper: true implies $group phase.

If it's working for you, @ralphievolt, and that is completely clear, I'll write it down and include in the docs (or link it at least for now).