1

I am trying to build a FacetOperation inside a loop in Java, but I am only getting the result of the first operation. Here's my code:

FacetOperation facetOperation = null;
for (int key = 0; key < 2; key++) {
    if (facetOperation == null) {
        facetOperation = facet(match(ctx -> basicQueryOriginal.getQueryObject()),
                project().and(DATA_SOURCE_ID).as("id"),
                group("id").count().as("count"),
                project("count").andExclude("_id")
        ).as("Category " + key);
    } else {
        facetOperation.and(match(ctx -> basicQueryOriginal.getQueryObject()),
                project().and(DATA_SOURCE_ID).as("id"),
                group("id").count().as("count"),
                project("count").andExclude("_id")
        ).as("Category " + key);
    }
}

Aggregation agg = newAggregation(facetOperation);
AggregationResults<Document> groupResults = mongoTemplate.aggregate(agg, "collection", Document.class);
Document facet = groupResults.getMappedResults().get(0);
facet.forEach((key, value) -> {
    countDtos.add(new CountDto(key, ((ArrayList) value).size()));
});

The loop is intended to create multiple FacetOperation operations, but when I run the code, I am only getting the result for only Category 0.

enter image description here

I also want to get result of Category 1, I am using MongoDB Java driver and Spring Data MongoDB. Can anyone help me figure out what's wrong with my code?

Additionally, without loop it works as mentioned in following answer Multiple facets. But my need is to achieve this using loop.

Update

Solution suggested by @valijon works for me. Now I have also created a Text Index in collection. I am able to add sorting on this in my basic query and it works fine using this:

basicQuery.fields().projectAs(MongoExpression.create("'$meta' : 'textScore'"), "score");
Document document = new Document("score", MongoExpression.create("'$meta' : 'textScore'").toDocument());
basicQuery.setSortObject(document) 

Now when I try to use this basic query in Aggregation. I get following error:

org.springframework.data.mongodb.UncategorizedMongoDbException: Command failed with error 40218 (Location40218): 'query requires text score metadata, but it is not available' on server localhost:27017.

How can I make aggregation to either ignore the text index or make use of $meta?

Zeeshan Ali
  • 130
  • 1
  • 14
  • 1
    You need to assign to `facetOperation` variable each new query criteria: `facetOperation = facetOperation.and(...)`. – Valijon Apr 20 '23 at 07:08
  • Hi @Valijon I hope you are doing fine. You suggestion worked for me. Now I have to modify it to also take in account text index while performing aggregation. I searched and tried alot without any luck. I would be really thankful if you could let me know if its possible. – Zeeshan Ali Jul 19 '23 at 20:12
  • Hey. Could you please update your question and add some sample data and expected result? – Valijon Jul 23 '23 at 08:36
  • @Valijon Thank you. I had found the solution, will add as answer. – Zeeshan Ali Jul 25 '23 at 14:52

1 Answers1

0

I have implemented the change suggested by @Valijon and was able to add support for text index in aggregation pipeline.

Here is my final code which works:

FacetOperation facetOperation = null;
for (int key = 0; key < 2; key++) {
    if (facetOperation == null) {
        facetOperation = facet(match(ctx -> basicQueryOriginal.getQueryObject()),
                project().and(DATA_SOURCE_ID).as("id"),
                group("id").count().as("count"),
                project("count").andExclude("_id")
        ).as("Category " + key);
    } else {
        facetOperation = facetOperation.and(match(ctx -> basicQueryOriginal.getQueryObject()),
                project().and(DATA_SOURCE_ID).as("id"),
                group("id").count().as("count"),
                project("count").andExclude("_id")
        ).as("Category " + key);
    }
}
MatchOperation matchOperation = Aggregation.match(
        new TextCriteria().matchingAny("[street]").caseSensitive(false)
);
AddFieldsOperation addFieldsOperation = addFields()
        .addFieldWithValue("score", new Document("$meta", "textScore")).build();

Aggregation agg = newAggregation(matchOperation, addFieldsOperation, facetOperation);
AggregationResults<Document> groupResults = mongoTemplate.aggregate(agg, "collection", Document.class);
Document facet = groupResults.getMappedResults().get(0);
facet.forEach((key, value) -> {
    countDtos.add(new CountDto(key, ((ArrayList) value).size()));
});
Zeeshan Ali
  • 130
  • 1
  • 14