ArrayQuery: ORM-like Querying for JavaScript Arrays

ArrayQuery: ORM-like Querying for JavaScript Arrays

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.

Online Documentation
GitHub Repository

Please follow and like us:
Pin Share