mbouclas
mbouclas

Reputation: 744

Create a price range facet in mongodb aggregation pipeline

My document structure looks like this

{
title : 'a product',
price : 10
}

What i would like to do is a dynamic price range facet which would look like this

[
        {
            facet : '0-30',
            count : 5
        },
        {
            facet : '30-100',
            count : 40
        }
]

Obviously there would be a fixed interval, for example 50. I used to have ElasticSearch do this for me using the histogram function but i can't get it to work in mongo. I suppose, one could do a map reduce to get it done, but i wonder if there is a way to added to my aggregation pipeline.

Upvotes: 3

Views: 1373

Answers (1)

chridam
chridam

Reputation: 103445

You could try an aggregation pipeline where you can project the facet field using the $cond operator. To demonstrate this, suppose you have a collection with the following documents:

db.collection.insert([
    { "title" : "Product STU", "price" : 10 },
    { "title" : "Product XYZ", "price" : 50 },
    { "title" : "Product PCT", "price" : 14 },
    { "title" : "Product DEF", "price" : 89 },
    { "title" : "Product DYQ", "price" : 34 },
    { "title" : "Product ABC", "price" : 40 },
    { "title" : "Product JKL", "price" : 50 },
    { "title" : "Product PQR", "price" : 75 },
    { "title" : "Product MNO", "price" : 81 },
    { "title" : "Product VWN", "price" : 5 },
    { "title" : "Product KLM", "price" : 63 }
]);

The aggregation pipeline that will achieve the desired result is as follows:

db.collection.aggregate([
    {
        "$match": {
            "price": { "$lte": 100, "$gte": 0 }
        }
    },
    {
        "$project": {
            "title": 1,
            "price": 1,
            "_id": 0,
            "facet": {
                "$cond": [ { "$gte": [ "$price", 30 ] }, "30-100", "0-30" ]
            }
        }
    },
    {
        "$group": {
            "_id": "$facet",
            "count": {
                "$sum": 1
            }
        }
    },
    {
        "$project": {
            "facet": "$_id",
            "_id": 0,
            "count": 1
        }
    }
])

Output:

/* 1 */
{
    "result" : [ 
        {
            "count" : 8,
            "facet" : "30-100"
        }, 
        {
            "count" : 3,
            "facet" : "0-30"
        }
    ],
    "ok" : 1
}

Upvotes: 2

Related Questions