Skip to main content

Echo Database Queries

Introduction

Echo Database provides a powerful yet intuitive way to query and retrieve data from your collections. Whether you need to fetch all records, find specific items, or perform complex filtering operations, Echo Database's query system offers the tools you need to efficiently access your data.

In this guide, we'll explore how to construct queries in Echo Database, from basic operations to more advanced techniques. We'll cover filtering, sorting, pagination, and other essential query capabilities that will help you build effective data access patterns in your applications.

Basic Query Operations

Fetching All Records

The simplest query is retrieving all records from a collection. Here's how to do it:

javascript
const allUsers = await db.users.getAll();
console.log(allUsers);

Output:

[
{ id: '1', name: 'Alice', age: 28 },
{ id: '2', name: 'Bob', age: 32 },
{ id: '3', name: 'Charlie', age: 24 }
]

Getting a Single Record by ID

To fetch a specific record using its unique ID:

javascript
const user = await db.users.get('2');
console.log(user);

Output:

{ id: '2', name: 'Bob', age: 32 }

Filtering Records

Echo Database offers powerful filtering capabilities to find records that match specific criteria.

Simple Filtering

To find records that match an exact field value:

javascript
const youngUsers = await db.users.find({ age: 24 });
console.log(youngUsers);

Output:

[{ id: '3', name: 'Charlie', age: 24 }]

Advanced Filtering with Operators

Echo Database supports various comparison operators for more complex queries:

javascript
// Find users older than 25
const olderUsers = await db.users.find({
age: { $gt: 25 }
});
console.log(olderUsers);

Output:

[
{ id: '1', name: 'Alice', age: 28 },
{ id: '2', name: 'Bob', age: 32 }
]

Here are the commonly used comparison operators:

  • $eq: Equal to (default when not specified)
  • $ne: Not equal to
  • $gt: Greater than
  • $gte: Greater than or equal to
  • $lt: Less than
  • $lte: Less than or equal to
  • $in: In an array of values
  • $nin: Not in an array of values

Compound Filtering with Logical Operators

You can combine multiple conditions using logical operators:

javascript
// Find users between ages 25 and 30
const middleAgedUsers = await db.users.find({
$and: [
{ age: { $gte: 25 } },
{ age: { $lte: 30 } }
]
});
console.log(middleAgedUsers);

Output:

[{ id: '1', name: 'Alice', age: 28 }]

Logical operators include:

  • $and: All conditions must be true
  • $or: At least one condition must be true
  • $not: Negates the condition

Sorting Results

You can sort query results by one or more fields:

javascript
// Sort users by age in ascending order
const sortedUsers = await db.users.find({}, {
sort: { age: 1 }
});
console.log(sortedUsers);

Output:

[
{ id: '3', name: 'Charlie', age: 24 },
{ id: '1', name: 'Alice', age: 28 },
{ id: '2', name: 'Bob', age: 32 }
]

For descending order, use -1 instead of 1:

javascript
// Sort users by age in descending order
const reverseSortedUsers = await db.users.find({}, {
sort: { age: -1 }
});
console.log(reverseSortedUsers);

Output:

[
{ id: '2', name: 'Bob', age: 32 },
{ id: '1', name: 'Alice', age: 28 },
{ id: '3', name: 'Charlie', age: 24 }
]

Pagination

For collections with many records, pagination helps manage data in chunks:

javascript
// Get the first page with 2 items per page
const firstPage = await db.users.find({}, {
limit: 2,
skip: 0
});
console.log(firstPage);

// Get the second page
const secondPage = await db.users.find({}, {
limit: 2,
skip: 2
});
console.log(secondPage);

Output (firstPage):

[
{ id: '1', name: 'Alice', age: 28 },
{ id: '2', name: 'Bob', age: 32 }
]

Output (secondPage):

[
{ id: '3', name: 'Charlie', age: 24 }
]

Projection: Selecting Specific Fields

You can limit the fields returned in your query results using projection:

javascript
// Get only names from user records
const userNames = await db.users.find({}, {
projection: { name: 1 }
});
console.log(userNames);

Output:

[
{ id: '1', name: 'Alice' },
{ id: '2', name: 'Bob' },
{ id: '3', name: 'Charlie' }
]

To exclude fields instead of including them:

javascript
// Get everything except the age field
const usersWithoutAge = await db.users.find({}, {
projection: { age: 0 }
});
console.log(usersWithoutAge);

Output:

[
{ id: '1', name: 'Alice' },
{ id: '2', name: 'Bob' },
{ id: '3', name: 'Charlie' }
]

Aggregation Operations

Echo Database provides basic aggregation functions for common operations:

Count

Count the number of records matching a query:

javascript
const adultCount = await db.users.count({ age: { $gte: 18 } });
console.log(`Number of adult users: ${adultCount}`);

Output:

Number of adult users: 3

Sum, Average, Min, Max

For numeric fields, you can perform calculations:

javascript
const stats = await db.users.aggregate([
{ $match: {} }, // Match all records
{
$group: {
_id: null,
totalAge: { $sum: "$age" },
averageAge: { $avg: "$age" },
youngestAge: { $min: "$age" },
oldestAge: { $max: "$age" }
}
}
]);
console.log(stats[0]);

Output:

{
_id: null,
totalAge: 84,
averageAge: 28,
youngestAge: 24,
oldestAge: 32
}

Real-World Examples

User Authentication

javascript
async function authenticateUser(email, password) {
// Find user with matching email
const user = await db.users.findOne({ email });

if (!user) {
return { success: false, message: "User not found" };
}

// In a real app, you would hash and compare passwords
if (user.password === password) {
return { success: true, user: { id: user.id, name: user.name, email: user.email } };
} else {
return { success: false, message: "Incorrect password" };
}
}

// Usage
const result = await authenticateUser("[email protected]", "securepass");
if (result.success) {
console.log("Login successful:", result.user);
} else {
console.error("Login failed:", result.message);
}

Product Filtering in E-commerce

javascript
async function searchProducts(options) {
const query = {};

// Filter by category
if (options.category) {
query.category = options.category;
}

// Filter by price range
if (options.minPrice !== undefined || options.maxPrice !== undefined) {
query.price = {};
if (options.minPrice !== undefined) {
query.price.$gte = options.minPrice;
}
if (options.maxPrice !== undefined) {
query.price.$lte = options.maxPrice;
}
}

// Search by name
if (options.searchTerm) {
query.name = { $regex: options.searchTerm, $options: 'i' }; // Case-insensitive search
}

// Define sort order
const sort = {};
if (options.sortBy) {
sort[options.sortBy] = options.sortOrder === 'desc' ? -1 : 1;
} else {
sort.name = 1; // Default: sort by name ascending
}

// Pagination
const limit = options.limit || 10;
const skip = (options.page || 0) * limit;

// Execute query
return await db.products.find(query, { sort, limit, skip });
}

// Example usage
const electronicsUnder1000 = await searchProducts({
category: 'electronics',
maxPrice: 1000,
sortBy: 'price',
page: 0,
limit: 5
});
console.log(electronicsUnder1000);

Task Management Dashboard

javascript
async function getUserTaskSummary(userId) {
// Get all tasks for the user
const allTasks = await db.tasks.find({ userId });

// Get counts by status
const pending = await db.tasks.count({ userId, status: 'pending' });
const inProgress = await db.tasks.count({ userId, status: 'in-progress' });
const completed = await db.tasks.count({ userId, status: 'completed' });

// Get upcoming tasks (due in the next 7 days)
const today = new Date();
const nextWeek = new Date();
nextWeek.setDate(today.getDate() + 7);

const upcoming = await db.tasks.find({
userId,
dueDate: {
$gte: today.toISOString().split('T')[0],
$lte: nextWeek.toISOString().split('T')[0]
},
status: { $ne: 'completed' }
}, {
sort: { dueDate: 1 },
limit: 5
});

return {
counts: { total: allTasks.length, pending, inProgress, completed },
upcomingTasks: upcoming
};
}

// Example usage
const taskSummary = await getUserTaskSummary('user123');
console.log(taskSummary);

Summary

In this guide, we've covered the essentials of querying data in Echo Database:

  • Basic operations like fetching all records or a single record by ID
  • Filtering data using simple criteria and advanced operators
  • Sorting results to organize your data
  • Implementing pagination for large data sets
  • Selecting specific fields with projection
  • Performing simple aggregation operations
  • Real-world examples demonstrating practical applications

Echo Database's query system is designed to be intuitive for beginners while offering the flexibility needed for more complex data operations. By mastering these query techniques, you'll be able to efficiently retrieve and manipulate data in your applications.

Additional Resources

Exercises

  1. Basic Query: Write a query to find all users who are exactly 30 years old.
  2. Compound Query: Find all products that are either in the "electronics" category with a price under 500orinthe"books"categorywithapriceunder500 or in the "books" category with a price under 30.
  3. Sorting and Pagination: Write a query to get the 5 most expensive products in the "clothing" category.
  4. Aggregation: Calculate the average price of products in each category.
  5. Real-world Challenge: Implement a function that returns a list of blog posts, filtered by tag, sorted by date, with pagination, including the author's name and avatar (hint: you'll need to use a join-like operation between posts and users collections).

Happy querying!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)