2

Here is my aggregation query

blockColctn.aggregate([{
    "$match": {
        "number": blockNumber
    }

    },
    {
    "$project": {
        "transactions.to": "$transactions.to",
        "transaction": "$transactions",
        "transactions.hash": "$transactions.hash",


    }
    },
    {
    "$lookup": {
        "from": "token_collections",
        "localField": "transactions.to",
        "foreignField": "tokencontractaddress",
        "as": "tokenaccount"
    }
    },
    {
    "$project": {
       "total":getTotal("transactions.hash")
    }
    }])

I am calling getTotal in $project it works fine, however, I would like to pass transactions.hash column value as the function argument. I found a similar issue related to mine Custom functions calculated columns mongodb projection

But it doesn't tell about argument passing

2
  • Where are you calling blockColctn.aggregate() from? You can create a composable function that takes in the aggregate and getTotal methods Commented Jun 25, 2018 at 14:19
  • Its from a function can you give an example?? Commented Jun 26, 2018 at 4:57

1 Answer 1

2

Would start by refactoring the above, first creating a function that takes in the column total value as the function argument and returns the pipeline array:

const getAggregatePipeline = total => ([
    { "$match": {
        "number": blockNumber
    } },
    { "$project": {
        "transactions.to": "$transactions.to",
        "transaction": "$transactions",
        "transactions.hash": "$transactions.hash",
    } },
    { "$lookup": {
        "from": "token_collections",
        "localField": "transactions.to",
        "foreignField": "tokencontractaddress",
        "as": "tokenaccount"
    } },
    { "$project": { total } }
])

Now you can pass this on to the aggregate method as

blockColctn.aggregate(getAggregatePipeline(getTotal("transactions.hash")))

As you can see we're just nesting functions inside each other so that when they're called with a final value, the result explodes outwards through each layer. This can be further refactored to create a composition of all those functions (i.e. that returns a new function) with the following blueprint

const compose = (f1, f2, f3) => value => f1( f2( f3(value) ) )

You can then call this as

const agg = compose(blockColctn.aggregate, getAggregatePipeline, getTotal)("transactions.hash")

For a compose function that’s fully variadic, i.e. one that can take an arbitrarily long list of functions and then work right to left (inner to outer):

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.