I have the following types of requests.
server/controllerName/access_id/id/field/field_value/api_name
server/controllerName/access_id/id/field/field_value/field2/field_value/api_name
Few field examples:
1. start date and end date
2. user name
3. user group
Mongo DB data format:
Mongo DB stores user order details. Each order contains user detail[10 fields] and order details[30 fields]
API has to give by default last 30 days of orders if no date is mentioned.
My question:
How can I efficiently read this data from mongo db?
What I am currently doing:
I am parsing the httprequest
and adding these fields to a map
{"name":"gibbs", "category":"vip"}
I have to get all the documents where these two fields are matching and return the documents in the following form.
{
user: "gibbs",
total_Result: 10,
[
{
//order details items from doc 1
}
{
//order details from doc2
}
]
}
I am querying mongo db as follows.
MongoCollection<Document> mongoEngCollection = mongoDbReader.getCollection();
BasicDBObject andQuery = new BasicDBObject();
List<BasicDBObject> obj = new ArrayList<BasicDBObject>();
//Forming query using request parameter. requestAttributes contains map of request parameters.
for(Map.Entry<PathAttribute, PathValue<?>> entry : requestAttributes.entrySet()) {
String key = entry.getKey().getName();
obj.add(new BasicDBObject(key, entry.getValue().getRawValue()));
}
andQuery.put("$and", obj);
//Queryng mongo db
FindIterable<Document> documents = mongoEngCollection.find(andQuery);
Then I am iterating the documents and grouping the fields as the required format.
It is written using spring.
I am fine with schema changes, query changes, annotation methods as long as it is very fast and conceptually correct.
Please advise me.
You've to use aggregation framework. Statically import all the methods of helper classes and use the below code.
Use of BasicDBObject
is deprecated in newer 3.x driver api. You should use the new class Document
for similar needs.
import static com.mongodb.client.model.Accumulators.*;
import static com.mongodb.client.model.Aggregates.*;
import static java.util.Arrays.asList;
import static com.mongodb.client.model.Filters.*;
import static com.mongodb.client.model.Projections.*;
import org.bson.conversions.Bson;
MongoCollection<Document> mongoEngCollection = mongoDbReader.getCollection();
List<Bson> obj = new ArrayList<>();
//Forming query using request parameter. requestAttributes contains map of request parameters.
for(Map.Entry<PathAttribute, PathValue<?>> entry : requestAttributes.entrySet()) {
String key = entry.getKey().getName();
//Check if key is not date and set the start and end date
obj.add(eq(key, entry.getValue().getRawValue()));
}
//Build aggregation stages
Bson match = match(and(obj));
Bson group = group(
first("user", "$name"),
sum("total_results", 1),
push("results", "$$ROOT")
);
Bson projection = project(fields(excludeId()));
//Query Mongodb
List<Document> results = mongoEngCollection .aggregate(asList(match, group, projection)).into(new ArrayList<Document>());
More about aggregation here https://docs.mongodb.com/manual/reference/operator/aggregation/
This can be achieved using Projections and Lookups in MongoDB. Apply self joins https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ Limit what to bring https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
I hope you can figure out easily how to write the query.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With