Introducing ArrayQuery: Powerful ORM-like Querying for JavaScript Arrays
Are you tired of writing complex logic to filter, sort, and paginate arrays in your JavaScript applications? Meet ArrayQuery, a powerful TypeScript library that brings ORM-like querying capabilities to local arrays. With ArrayQuery, you can manipulate and retrieve data from arrays with ease, using a familiar and intuitive API.
Key Features
- 📄 Pagination: Easily paginate through large datasets
- 🔎 Searching: Perform full-text search across multiple fields
- 🧠Filtering: Apply complex filters with various match modes
- 🔢 Sorting: Order results based on any field, including nested properties
Getting Started
First, install ArrayQuery in your project:
# npm
npm install @chronicstone/array-query
# yarn
yarn add @chronicstone/array-query
# pnpm
pnpm add @chronicstone/array-query
# bun
bun add @chronicstone/array-query
Now, let's dive into some examples to see how ArrayQuery can simplify your data manipulation tasks.
Basic Usage
Here's a simple example that demonstrates filtering, sorting, and pagination:
import { query } from '@chronicstone/array-query'
const users = [
{ id: 1, name: 'John Doe', age: 30, role: 'admin' },
{ id: 2, name: 'Jane Smith', age: 28, role: 'user' },
{ id: 3, name: 'Bob Johnson', age: 35, role: 'user' },
{ id: 4, name: 'Alice Brown', age: 26, role: 'admin' },
{ id: 5, name: 'Charlie Davis', age: 32, role: 'user' },
]
const result = query(users, {
filter: [
{ key: 'age', matchMode: 'greaterThan', value: 25 },
{ key: 'role', matchMode: 'equals', value: 'user' }
],
sort: { key: 'age', dir: 'desc' },
page: 1,
limit: 2
})
console.log(result)
This query will return:
{
rows: [
{ id: 3, name: 'Bob Johnson', age: 35, role: 'user' },
{ id: 5, name: 'Charlie Davis', age: 32, role: 'user' },
{ id: 2, name: 'Jane Smith', age: 28, role: 'user' }
],
totalPages: 2,
totalRows: 3
}
In this example, we filtered users older than 25 with the 'user' role, sorted them by age in descending order, and retrieved the first page with 2 items per page.
Searching
ArrayQuery also supports full-text search across multiple fields:
import { query } from '@chronicstone/array-query'
const articles = [
{ id: 1, title: 'Introduction to JavaScript', content: 'JavaScript is a programming language...', author: 'John Doe' },
{ id: 2, title: 'Python for Beginners', content: 'Python is known for its simplicity...', author: 'Jane Smith' },
{ id: 3, title: 'Advanced JavaScript Techniques', content: 'Learn about closures, promises, and async/await...', author: 'Bob Johnson' },
{ id: 4, title: 'Data Science with Python', content: 'Explore data analysis and machine learning...', author: 'Alice Brown' },
]
const result = query(articles, {
search: {
value: 'javascript',
keys: ['title', 'content']
},
sort: { key: 'title', dir: 'asc' }
})
console.log(result)
This query will return:
{
rows: [
{ id: 3, title: 'Advanced JavaScript Techniques', content: 'Learn about closures, promises, and async/await...', author: 'Bob Johnson' },
{ id: 1, title: 'Introduction to JavaScript', content: 'JavaScript is a programming language...', author: 'John Doe' }
]
}
This search found all articles containing 'javascript' in either the title or content, and sorted them by title.
The library also gives you control on case sensitivity, either globally or per searched property.
Sorting
ArrayQuery offers powerful sorting capabilities that go beyond simple single-field sorting. Let's explore some advanced sorting features.
Multi-Field Sorting
You can sort your data based on multiple fields, specifying the order for each:
import { query } from '@chronicstone/array-query'
const employees = [
{ id: 1, name: 'Alice', department: 'Sales', salary: 50000 },
{ id: 2, name: 'Bob', department: 'IT', salary: 60000 },
{ id: 3, name: 'Charlie', department: 'Sales', salary: 55000 },
{ id: 4, name: 'David', department: 'IT', salary: 65000 },
{ id: 5, name: 'Eve', department: 'Sales', salary: 52000 },
]
const result = query(employees, {
sort: [
{ key: 'department', dir: 'asc' },
{ key: 'salary', dir: 'desc' }
]
})
console.log(result.rows)
This will sort employees first by department (ascending) and then by salary (descending) within each department:
[
{ id: 4, name: 'David', department: 'IT', salary: 65000 },
{ id: 2, name: 'Bob', department: 'IT', salary: 60000 },
{ id: 3, name: 'Charlie', department: 'Sales', salary: 55000 },
{ id: 5, name: 'Eve', department: 'Sales', salary: 52000 },
{ id: 1, name: 'Alice', department: 'Sales', salary: 50000 }
]
Custom Sorting with Parser
ArrayQuery allows you to use a parser function to transform values before comparison. This is particularly useful when dealing with complex data types or when you need custom sorting logic.
import { query } from '@chronicstone/array-query'
const products = [
{ id: 1, name: 'Laptop', price: '$1200' },
{ id: 2, name: 'Smartphone', price: '$800' },
{ id: 3, name: 'Tablet', price: '$600' },
{ id: 4, name: 'Smartwatch', price: '$300' },
]
const result = query(products, {
sort: {
key: 'price',
dir: 'desc',
parser: (value) => parseInt(value.replace('$', ''))
}
})
console.log(result.rows)
This will sort products by price in descending order, correctly parsing the string prices:
[
{ id: 1, name: 'Laptop', price: '$1200' },
{ id: 2, name: 'Smartphone', price: '$800' },
{ id: 3, name: 'Tablet', price: '$600' },
{ id: 4, name: 'Smartwatch', price: '$300' }
]
You can also use built-in parsers for common scenarios:
const result = query(mixedData, {
sort: { key: 'value', dir: 'asc', parser: 'number' }
})
Available built-in parsers are 'number', 'string', and 'boolean'.
These advanced sorting capabilities allow you to handle complex sorting scenarios with ease, making ArrayQuery a powerful tool for data manipulation in your JavaScript and TypeScript projects.
Filtering
ArrayQuery offers a flexible and powerful filtering system that can handle both simple and complex query scenarios.
Filtering Strategies
ArrayQuery supports two main filtering strategies:
- Simple Filters: A list of conditions that are all combined with AND logic.
- Filter Groups: Create logical groups of filters, to handle more complex scenarios & granular filtering
Simple Filters
Simple filters are straightforward and easy to use:
import { query } from '@chronicstone/array-query'
const users = [
{ id: 1, name: 'Alice', age: 30, role: 'admin' },
{ id: 2, name: 'Arthur', age: 29, role: 'admin' },
{ id: 3, name: 'Bob', age: 25, role: 'user' },
{ id: 4, name: 'Charlie', age: 35, role: 'user' },
]
const result = query(users, {
filter: [
{ key: 'age', matchMode: 'greaterThan', value: 25 },
{ key: 'role', matchMode: 'equals', value: 'user' }
]
})
console.log(result.rows)
// Output: [{ id: 4, name: 'Charlie', age: 35, role: 'user' }]
Filter Groups
Filter groups allow for more complex logic:
const result = query(users, {
filter: [
{
operator: 'AND',
filters: [
{ key: 'role', matchMode: 'equals', value: 'admin' },
{ key: 'age', matchMode: 'greaterThanOrEqual', value: '30' },
]
},
{
operator: 'AND',
filters: [
{ key: 'role', matchMode: 'equals', value: 'user' },
{ key: 'age', matchMode: 'lowerThan', value: '30' },
]
}
]
})
:
console.log(result.rows)
// Output: [
// { id: 1, name: 'Alice', age: 30, role: 'admin' },
// { id: 3, name: 'Bob', age: 25, role: 'user' },
// ]
Available Match Modes
ArrayQuery supports a variety of match modes to cover different filtering needs:
equals
notEquals
contains
notContains
startsWith
endsWith
lessThan
lessThanOrEqual
greaterThan
greaterThanOrEqual
between
exists
arrayLength
objectMatch
Each match mode is designed for specific types of comparisons. For detailed information on how each match mode works, including examples and edge cases, please refer to our full documentation.
Conclusion
Originally built to make client-side pagination, filtering ,searching & sorting easy to implement on custom DataTable components on front-end apps, Array-Query has a simple & powerful API that you can use for any kind of local array querying.
Top comments (0)