CipherStash
CipherStash Documentation

Aggregates

Aggregation is the process of performing calculations on the retrieved data before it is returned to the client. Because your data is securely encrypted in CipherStash, there are a limited number of aggregations that can be performed. At present, the only available aggregation is to count the number of returned records. Securely supporting additional aggregations is an area of active research.

We maintain a page listing what CipherStash can and can’t do.

Requesting Aggregation

You specify an aggregation to apply by calling the aggregate method on he object that is passed into the query block for Collection#query. It takes two arguments: the index to aggregate on, and the aggregation type.

At present, since the only available aggregation is :count, the index name is technically unnecessary, but it is required for consistency with future aggregations. The name of any extant index will be accepted.

As an example, to get a count of all the movies from 1993:

movies.query do |m|
  m.year.eq(1993)
  m.aggregate("year", :count)
end

Getting Aggregation Results

The results of any specified aggregations are available in the QueryResult#aggregates method. This is an array of Aggregate objects representing the aggregation results, from which you can pick out the one you want. For example, expanding on our example above:

res = movies.query do |m|
  m.year.eq(1993)
  m.aggregate("year", :count)
end

agg = res.aggregates.find { |a| a.operation == :count && a.index == "year" }

puts "There were #{agg.value} movies made in 1993"

Skipping record retrieval

If you’re interested in the aggregates of your query, there’s a good chance you’re not interested in the contents of the records themselves. For this reason, you can request that the query response not include the record data, and only return aggregate data. This reduces query processing and network transmission time, especially for results that would include a lot of records.

To do this, simply set the record response limit to 0 on the object passed to the query block, like this:

res = movies.query do |m|
  m.year.eq(1993)
  m.aggregate("year", :count)
  m.limit(0)
end

The QueryResult#records method will then be an empty array.

Aggregation vs Limits

There are default limits on the number of records that are returned by a query, and you can specify an alternate limit with the #limit method on the query block object. However, this limit only applies to the records returned from the query. Aggregations always apply to all of the records that were matched by the query constraints, regardless of the number of records actually returned.