Dynamic Aggregation stages using string template
See original GitHub issueRelated with the issue 102 I wanted to add facet aggregation.
This time I used string templates. ( if it is possible to add facet to the answer in issue 102, it would also help, but anyway I chose string templates this time).
I could dynamically constructed the string template like this, and it worked, but it is dirty:) Do you think this kind of solution is good? Any suggestions?
If the pipeline method would accept input of an array (array of stages), this kind of dynamic (optional) aggregations would be easier? Would you consider adding this feature?
[HttpGet("search-facet")]
public async Task<IActionResult> SearchAndFacet(FilterProductDTO dto)
{
int page = dto.Page.HasValue ? dto.Page.Value : 1;
int pageSize = dto.PageSize.HasValue ? dto.PageSize.Value : 10;
int skip = (page - 1) * pageSize;
var stages = new List<string>();
if (!string.IsNullOrEmpty(dto.SearchTerm))
{
stages.Add(@"{$match: {
$text: { $search: '<search_term>' }
}}".Replace("<search_term>", dto.SearchTerm));
stages.Add(@" {$sort: {
score: { $meta: 'textScore' }
}}");
}
if (!string.IsNullOrEmpty(dto.CategoryId))
{
stages.Add(@" {
'$match': {
'Category': new ObjectId('<category_id>')
}
}".Replace("<category_id>", dto.CategoryId));
}
if (dto.MinPrice.HasValue)
{
stages.Add(@" {
'$match': {
'Price': { $gte: <min_price> }
}
}".Replace("<min_price>", dto.MinPrice.Value.ToString(new NumberFormatInfo() { NumberDecimalSeparator = "."})));
}
if (dto.MaxPrice.HasValue)
{
stages.Add(@" {
'$match': {
'Price': { $lte: <max_price> }
}
}".Replace("<max_price>", dto.MaxPrice.Value.ToString(new NumberFormatInfo() { NumberDecimalSeparator = "." })));
}
stages.Add(@"{$facet: {
TotalRecords: [
{
$count: 'total'
}
],
Products: [
{
$skip: <skip>
},
{
$limit: <limit>
}
]
}}"); //.Replace("<skip>", skip.ToString()).Replace("<limit>", pageSize.ToString()));
stages.Add(@"{$addFields: {
TotalRecords: {
$arrayElemAt: [ '$TotalRecords.total', 0]
}
}}");
var template = $"[{string.Join(',', stages)}]";
var pipeline = new Template<ProductEntity, ProductSearchResultDTO>(template)
.Tag("skip", skip.ToString())
.Tag("limit", pageSize.ToString());
var products = await DB.PipelineAsync(pipeline);
return Ok(products);
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (4 by maintainers)
Top Results From Across the Web
Best way to form an aggregate dynamic mongo query ...
I will form the query dynamically to get the result, so there are two options: either I can create a query in my...
Read more >Dynamic MongoDB Aggregations - Roger Kitain
We've seen how to specify MongoDB aggregations for querying document contents using an aggregation that queries for specific array elements. Now ...
Read more >String templates
Examples · Aggregation pipeline · Aggregation pipeline with different result type · Find with match expression · Update with aggregation pipeline · Update...
Read more >A MongoDB Aggregation Example with $match, $group & $ ...
Follow along this MongoDB aggregation example that uses $match, $group and $sort to query Chicago housing data, sample dataset included.
Read more >Build a NodeJS MongoDB Aggregation Pipeline in 3 Easy ...
This post lists the different MongoDB Aggregation Stages and the steps to set up NodeJS MongoDB Aggregation Pipeline using MongoDB Atlas ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Great, I wil try
ok thanks, AppendStage method is good enough 😃