11

i'm trying to make views in MongoDB to avoid unnecessary returns. In the documentation says that the aggregation functions can take variables with a double dollar sign, taking this in mind i have created a view that in this example should take one variable to filter customerIds and group the results to sum the payments of different documents.

Example:

db.createView(
  "viewName",
  "myCollection",
  [{
    $match: {  "customerId": "$$customerId", }
  },{
    $group: {
      _id: null,
      total: "$amount",
    }
  }]
)

The view is created OK and if i put some valid customerId in the aggregation function that works ok, but i don't have the slightest idea how to execute the view and pass the customerID that i need.

Any ideas? The mongodb documentation does not help me in this situation and i really need to create this as a view, since there are many applications that will connect to this view(s).

I have tried: db.viewName.find({customerId: "some valid id"});

Hugazo
  • 111
  • 2
  • 6

2 Answers2

1

You can access it just like a collection, for example I am creating a view via:

db.runCommand({
  create: 'AuthorsView',
  viewOn: 'authors',
  pipeline: [{
    "$group": {
      "_id": "$email",
      "count": {
        "$sum": 1
      }
    }
  }]
})

Since this is now an existing view I can simply do:

db.getCollection('AuthorsView').find({})

To see all the documents or to add more parameters to the find

Not sure what you mean by passing variables since views are just like collections ... you run queries against them via find & aggregate.

Akrion
  • 18,117
  • 1
  • 34
  • 54
  • 2
    The thing here is that the filter method acts after the aggregation pipeline. And by passing variables, i want the view to receive for example, a company id to only calculate the amounts for that company. for example: `db.myView({companyId: 'somevalidid'})` – Hugazo Oct 14 '18 at 22:31
  • 5
    Was there ever a solution found to this? It’s exactly what I’m looking for. I have a view that starts with a $match that restricts the data sent into the rest of the pipeline, but i need to pass in a value to the $match. – GoodEnuf Sep 29 '20 at 03:32
0

First, you can't pass variables to $match without $expr. There is no error because "$$..." is interpreted as a string.

Second, If we fix things like this:

db.createView(
  "viewName",
  "myCollection",
  [{
    $match: {$expr:{$eq:["$customerId","$$customerId"]}}, }
  },{
    $group: {
      _id: null,
      total: "$amount",
    }
  }]
)

But $$ is not a system variable, so this won't work. You could pass a system variable like $$ROOT or a field path $field.path; the user-defined variables are made up of system variables or collection data.

Minsky
  • 2,277
  • 10
  • 19