1

I am designing a flexible web service to aggregate data.

If we use sales as an example. A sales resource has properties of:

  • Sales person
  • Product
  • Price
  • Customer
  • Id
  • Department
  • Date
  • etc.

So the basic URI to access sales would be similar to the following:

api/sales/{id}

I need to design URIs to meet the following requirements:

  1. Total number of sales for a department
  2. Total number of sales for a person of a product
  3. month

So, three basic requirements. Grouping, filtering and selection of results (analogous to GROUP BY, WHERE and SELECT).

How to design the URI? The real problem for me is how to design the grouping. Here are some ideas I have been considering:

  1. Keep the current URI design but add additional parameters:

    E.g

    /api/sales?groupby=department&groupby=customer
    
  2. New URI:

    /api/sales-aggregator?groupby=department&groupby=customer
    
  3. Including the grouping as part of the path:

    /api/sales-aggregator/department/customer
    

    But the order of department and customer is arbitrary.

  4. Alternative path solution

    /api/sales-aggregator;groupby=department,groupby=customer

Recommendations?

unor
  • 92,415
  • 26
  • 211
  • 360
Stuart
  • 143
  • 9

1 Answers1

0

I would use the 3 or 4 with some modification.

The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by one or more columns.

SQL GROUP BY Syntax

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

If you need something general, so there would be a lot of different solutions, then using the aggregator word is okay. If you want to use it with GET, then I think aggregation would be a better word. With POST it is okay to use aggregator.

If the link does not have to fulfill general purposes, then you should rename the aggregation to something specific, which describes the result of the aggregate function, or the query (if you use multiple aggregate functions). For example GET /api/sales-person:123/sales-count or GET /api/sales-count?sales-person=123.

Another option to return the aggregations and the items used by the aggregate functions in a single response.

GET /api/sales/?sales-person=123 -> 200 ok
{
    count: 123,
    total: {
        value: 1234567,
        currency: "USD"
    },
    sales: [
        {
            id: 1,
            price: {value: 34556, currency: "USD"},
            ...
            links: {self: {href: "/api/sales/1"}}
        },
        ...
    ]
}

You can use this with preference headers if you want to enable / disable aggregations, item properties, etc. in the representation. (Don't forget to add prefer to the vary header if you use this, otherwise the cache control won't work properly.)

Community
  • 1
  • 1
inf3rno
  • 24,976
  • 11
  • 115
  • 197