As aggregation queries become increasingly complex, maintaining and understanding these structures can become challenging. This package addresses this issue by providing a fluid and flexible interface for building aggregation pipelines.
mongoose-pipeliner
offers a class and interface that can be used as an aggregation pipeline builder or extended to construct a customized builder. This tool is intended to significantly simplify the process of building and maintaining complex aggregation queries.
- Simplification of Complex Queries: Facilitates the construction of complex aggregation pipelines.
- Design Patterns: Implements Builder and Template patterns for enhanced flexibility.
- Function Chaining: Enables a more readable and maintainable query building approach.
- Aggregation Operations: Supports all basic MongoDB aggregation operations and some advanced ones like lookup, set, unset, unwind, etc.
- Customization and Extensibility: Allows users to extend and customize the builder according to their specific needs.
npm install mongoose-pipeliner
Inject pipeline stages using the builder's methods. The builder will automatically add the stages to the pipeline in the order they are injected.
const { User } from './models';
const { AggregationPipelineBuilder } from 'mongoose-pipeliner';
const builder = new AggregationPipelineBuilder();
builder.filter({ status: 'active' }).project({ name: 1, status: 1 }).limit(10);
const pipeline = builder.assemble();
// Use your pipeline with your Mongoose model
User.aggregation(pipeline).exec((err, result) => {
// ...
});
You can perform aggregation operations directly from builder class.
const { User } from './models';
const { AggregationPipelineBuilder } from 'mongoose-pipeliner';
const builder = new AggregationPipelineBuilder(User);
builder.filter({ status: 'active' }).project({ name: 1, status: 1 }).limit(10);
const result = await builder.execute();
Some useful implementation strategies to implement a pipeline-builder
is to group operations that can be reused by multiple components or services through the template class strategy or inheritance.
import { AggregationPipelineBuilder } from 'mongoose-pipeliner';
import { User } from './models';
class MyCustomUserPipelineBuilder extends AggregationPipelineBuilder {
myCustomOperation() {
return this.filter({ status: 'active' }).project({ name: 1, status: 1 }).limit(10).skip().execute();
}
}
// Use your pipeline with your Mongoose model
const result = await new MyCustomUserPipelineBuilder(User).myCustomOperation();
or
import { AggregationPipelineBuilder } from 'mongoose-pipeliner';
import { User } from './models';
class MyCustomUserPipelineBuilder extends AggregationPipelineBuilder {
searchActive() {
return this.filter({ status: 'active' }).project({ name: 1, status: 1 });
}
searchInactive() {
return this.filter({ status: 'inactive' }).project({ name: 1, status: 1 });
}
standardPagination(limit: number = 10, page: number = 1) {
return this.paginate(limit, page);
}
}
// Use your pipeline with your Mongoose model
const builder = await new MyCustomUserPipelineBuilder(User);
const first_search = builder.searchActive().standardPagination(10, 2).execute();
const second_search = builder.searchInactive().standardPagination(10, 2).execute();
Or simply define a pipeline-builder
as part of a utility class, service or component
that can be consumed or implemented throughout your application.
import { AggregationPipelineBuilder } from 'mongoose-pipeliner';
import { User } from './models';
/**
* @description Provide custom pipelines to be injected
* in some aggregation pipeline repository
*/
class UserPipelineProvider {
protected static builder = new AggregationPipelineBuilder(User);
static activePipeline() {
return builder.filter({ status: 'active' }).project({ name: 1, status: 1 }).assemble();
}
static inactivePipeline() {
return builder.filter({ status: 'inactive' }).project({ name: 1, status: 1 }).assemble();
}
static someComplexPipeline() {
return [].concat(this.activePipeline() /* my custom proxy pipeline */);
}
}
// Implement the provider class
class UserRepository {
async findActiveUsers() {
return User.aggregation(UserPipelineProvider.activePipeline()).exec();
}
async findInactiveUsers() {
return User.aggregation(UserPipelineProvider.inactivePipeline()).exec();
}
async findSomeComplexUsers() {
return User.aggregation(UserPipelineProvider.someComplexPipeline()).exec();
}
}
Contributions are welcome. If you have ideas for improving this package, please read our contribution guide.
- Fork the repository.
- Create a new branch for each feature or improvement.
- Submit a pull request with your changes.
This project is licensed under MIT License - Visit the license document file for details.