als-mongo-list
Version:
A flexible, lightweight MongoDB query utility for Node.js applications. Simplifies database operations with intuitive filtering, pagination, sorting, and field selection. Ideal for REST API endpoints, providing a primary List class that abstracts complex
220 lines (172 loc) • 7.03 kB
Markdown
# als-mongo-list
`als-mongo-list` is a Node.js library designed to help you quickly build search, filter, sort, and pagination logic for Mongoose-based MongoDB queries. It simplifies building complex query interfaces by providing a structured way to:
- Filter documents by various fields, including support for ranges, enums, dates, booleans, ObjectIds, and array fields.
- Search text fields using regular expressions with enhanced configuration options.
- Sort by specified keys, including strings, numbers, booleans, and dates.
- Paginate results efficiently, including total count and navigation controls.
- Dynamically generate input fields for building UI filters and sorting selectors.
## ChangeLog for Version 2.2.0
**Added Features:**
1. Boolean Fields Input Update:
- Boolean fields now use a `<select>` input instead of a `<input type="checkbox">`.
- Added an additional option "all" to include both true and false results (by default).
2. Improved Search Logic:
- If only one searchable field is configured, the search applies directly to that field.
- If multiple searchable fields are configured:
- A search input (type="search") is generated for the query text.
- Corresponding checkbox inputs for each field are provided to enable or disable specific fields in the search query.
3. Array Field Filtering:
- Added support for filtering array fields within documents.
- The library now generates filters for array fields, allowing regex-based or equality-based filtering.
4. For `searchIn`,`orderBy`,`populate`,`select` if key not in model's tree, console.warn will warn for it
## Installation
Install via npm:
```bash
npm install als-mongo-list
```
## Usage
First, define your Mongoose model and schema as usual:
```js
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
name: { type: String },
age: { type: Number, min: 18, max: 99 },
isActive: { type: Boolean },
userId: { type: mongoose.Types.ObjectId },
createdAt: { type: Date, default: Date.now },
status: { type: String, enum: ["active", "inactive", "pending"] },
tags: [{ type: String }], // Example array field
});
const UserModel = mongoose.model("User", userSchema);
```
Then, initialize `als-mongo-list` with your model:
```js
const List = require("als-mongo-list");
const list = new List(UserModel)
.searchIn("name", "tags") // Fields to include in search/filter.
.orderBy("age") // Fields allowed for sorting.
.populate("userId") // Fields to populate.
.select("name", "age", "status"); // Fields to select.
```
### Executing Queries
Once configured, you can execute queries by passing in query parameters and, optionally, an initial `search` object. Query parameters may include filters (e.g., `age_gte`, `age_lte`), sorting (`orderBy`), pagination (`currentPage`, `pageSize`), and full-text search (`search`).
**Example:**
```js
(async () => {
const query = {
search: "John",
age_gte: "25",
orderBy: "age",
currentPage: "0",
pageSize: "10",
};
const result = await list.exec(query, { userId: "someuserid" });
if (result.error) {
console.error("Query error:", result.error);
} else {
console.log(result.items); // Paginated array of documents
console.log(result.total); // Total number of documents matching the filters
console.log(result.inputs); // Input definitions for building a UI
console.log(result.query); // Query parameters (with normalized pagination)
}
})();
```
### Updated Features
#### Boolean Fields
- **New Input Type:** `Boolean` fields now use a `<select>` with the following options:
- `"all"`: No filtering (default).
- `"true"`: Includes documents where the field is `true`.
- `"false"`: Includes documents where the field is `false`.
**Example Input Definition:**
```json
{
"isActive": {
"tag": "select",
"name": "isActive",
"options": [
{ "value": "", "text": "all" },
{ "value": "true", "text": "true" },
{ "value": "false", "text": "false" }
]
}
}
```
#### Enhanced Search Logic
1. **Single Search Field:**
- If only one field is included in the search configuration, the query applies directly to that field without `$or`.
2. **Multiple Search Fields:**
- If multiple fields are configured, a `search` input is generated alongside checkboxes for each field. Users can enable or disable specific fields for inclusion in the search query.
**Example Input Definition:**
```json
{
"search": {
"tag": "input",
"type": "search",
"name": "search",
"keys": [
{ "tag": "input", "type": "checkbox", "name": "name", "checked": true },
{ "tag": "input", "type": "checkbox", "name": "tags", "checked": true }
]
}
}
```
#### Array Field Filtering
- Array fields are now supported for filtering. You can search for documents where any element in the array matches a given value (or regex).
**Example:**
Given a schema with an array field:
```js
tags: [{ type: String }];
```
You can perform a search:
```js
const query = { tags: "technology" };
const result = await list.exec(query);
```
The library will filter documents where the `tags` array contains `"technology"`.
### Dynamic Input Definitions
`als-mongo-list` generates metadata (`inputs`) about possible filters and sorts. These can be used to build dynamic UIs. For example, `result.inputs.filter` and `result.inputs.sort` provide configuration for creating input elements (like `<input>`, `<select>`, etc.) that match the filter and sort capabilities of the current configuration.
**Updated Example:** Boolean, search, and array fields are now supported dynamically:
```js
// Suppose `list.exec(query)` returns `result.inputs` as follows:
console.log(result.inputs);
/*
{
filter: {
search: {
tag: 'input',
type: 'search',
name: 'search',
keys: [
{ tag: 'input', type: 'checkbox', name: 'name', checked: true },
{ tag: 'input', type: 'checkbox', name: 'tags', checked: true }
]
},
isActive: {
tag: 'select',
name: 'isActive',
options: [
{ value: "", text: "all" },
{ value: "true", text: "true" },
{ value: "false", text: "false" }
]
},
tags: { tag: 'input', type: 'search', name: 'tags' },
age_gte: { tag: 'input', type: 'number', name: 'age_gte', min: 18, max: 99 },
age_lte: { tag: 'input', type: 'number', name: 'age_lte', min: 18, max: 99 },
},
sort: {
tag: 'select',
name: 'orderBy',
options: [
{ value: '-age', text: 'small_big', key: 'age' },
{ value: 'age', text: 'big_small', key: 'age' },
// ... other sort options
]
},
pagination: { /* pagination info from als-pagination *-/ }
}
*/
```