Mihir Shah
Mihir Shah

Reputation: 1809

Mongodb spring data group _id toLower or case insensitive

I have mongodb facet and aggregate query in spring boot using mongo template and aggregation query. everything works fine except case sensitivity of value. I have below query in mongodb:

db.getCollection('product').aggregate([{"colors":[{$unwind:"$variants"},
{"$group": {
        _id: { $toLower: "$variants.color" },
        count:{$sum:1},
        image : { $first: '$variants.color_image' },
    }}

]

I have equivalent spring data query:

Aggregation.facet(unwind("variants"), group("variants.color").count().as("count").first("variants.color_image").as("image"))
            .as("colors");

But here how can I mention toLower to group field?

Upvotes: 1

Views: 1531

Answers (1)

Valijon
Valijon

Reputation: 13103

Spring-boot does not allow complex aggregations as you can do in shell. So, you may apply such workaround.

Let's change your facet query by this (create new field where we set lower case color value):

db.collection.aggregate([
  {
    $facet: {
      "colors": [
        {
          $unwind: "$variants"
        },
        {
          $addFields: {
            "variants.color_lower": {
              $toLower: "$variants.color"
            }
          }
        },
        {
          "$group": {
            _id: "$variants.color_lower",
            count: {
              $sum: 1
            },
            image: {
              $first: "$variants.color_image"
            },

          }
        }
      ]
    }
  }
])

MongoPlayground

Now, Spring-Boot allows to define custom AggregationOperation (Generic solution: here):

public class LowerAggregationOperation implements AggregationOperation() {

    @Override
    public List<Document> toPipelineStages(AggregationOperationContext context) {

        return Arrays.asList(
            new Document("$addFields", 
                new Document("variants.color_lower", 
                    new Document("$toLower", "$variants.color")))
        );
    }

}

Now, you complete your facet aggregation:

Aggregation.facet(
    unwind("variants"), 
    new LowerAggregationOperation(),
    group("variants.color_lower").count().as("count").first("variants.color_image").as("image"))
.as("colors");

Upvotes: 2

Related Questions