feathers-elasticsearch supports both standard Feathers query syntax and Elasticsearch-specific queries.
All standard Feathers query operators are supported:
// Find messages with text equal to "Hello"
query: {
text: 'Hello'
}// $lt - less than
query: {
age: { $lt: 30 }
}
// $lte - less than or equal
query: {
age: { $lte: 30 }
}
// $gt - greater than
query: {
age: { $gt: 30 }
}
// $gte - greater than or equal
query: {
age: { $gte: 30 }
}
// $ne - not equal
query: {
status: { $ne: 'archived' }
}// $in - value in array
query: {
status: { $in: ['active', 'pending'] }
}
// $nin - value not in array
query: {
status: { $nin: ['archived', 'deleted'] }
}// $or - match any condition
query: {
$or: [
{ status: 'active' },
{ priority: 'high' }
]
}
// $limit - limit results
query: {
$limit: 10
}
// $skip - skip results (pagination)
query: {
$skip: 20
}
// $sort - sort results
query: {
$sort: {
createdAt: -1 // -1 for descending, 1 for ascending
}
}
// $select - select specific fields
query: {
$select: ['title', 'content', 'createdAt']
}On top of standard Feathers queries, feathers-elasticsearch supports Elasticsearch-specific query operators.
match_all query - Find all documents.
query: {
$all: true
}Example:
// Find all messages
const allMessages = await service.find({
query: { $all: true }
});prefix query - Find all documents which have the given field containing terms with a specified prefix (not analyzed).
query: {
user: {
$prefix: 'bo'
}
}Example:
// Find users whose name starts with "bo" (bob, bobby, etc.)
const users = await service.find({
query: {
name: { $prefix: 'bo' }
}
});wildcard query - Find all documents which have the given field containing terms matching a wildcard expression (not analyzed).
query: {
user: {
$wildcard: 'B*b'
}
}Wildcard characters:
*- matches zero or more characters?- matches exactly one character
Example:
// Find users matching pattern "B*b" (Bob, Barb, etc.)
const users = await service.find({
query: {
name: { $wildcard: 'B*b' }
}
});regexp query - Find all documents which have the given field containing terms matching a regular expression (not analyzed).
query: {
user: {
$regexp: 'Bo[xb]'
}
}Example:
// Find users matching regex "Bo[xb]" (Bob, Box)
const users = await service.find({
query: {
name: { $regexp: 'Bo[xb]' }
}
});exists query - Find all documents that have at least one non-null value in the specified fields.
query: {
$exists: ['phone', 'address']
}Example:
// Find users who have both phone and address fields
const users = await service.find({
query: {
$exists: ['phone', 'address']
}
});
// Find users who have an email field
const usersWithEmail = await service.find({
query: {
$exists: ['email']
}
});The inverse of exists - Find all documents missing the specified fields.
query: {
$missing: ['phone', 'address']
}Example:
// Find users who are missing both phone and address
const users = await service.find({
query: {
$missing: ['phone', 'address']
}
});match query - Full-text search. Find all documents which have the given fields matching the specified value (analyzed).
query: {
bio: {
$match: 'javascript'
}
}Example:
// Find articles mentioning "javascript" in the content
const articles = await service.find({
query: {
content: { $match: 'javascript' }
}
});
// The query is analyzed, so it will match variations like "JavaScript", "Javascript", etc.match_phrase query - Find all documents which have the given fields matching the specified phrase (analyzed).
query: {
bio: {
$phrase: 'I like JavaScript'
}
}Example:
// Find articles with the exact phrase "machine learning"
const articles = await service.find({
query: {
content: { $phrase: 'machine learning' }
}
});match_phrase_prefix query - Find all documents which have the given fields matching the specified phrase prefix (analyzed).
query: {
bio: {
$phrase_prefix: 'I like JavaS'
}
}Example:
// Find articles with phrases starting with "machine learn" (matches "machine learning", "machine learned", etc.)
const articles = await service.find({
query: {
content: { $phrase_prefix: 'machine learn' }
}
});This operator provides support for Elasticsearch array datatype. Find all documents which match all of the given criteria.
As any field in Elasticsearch can contain an array, this is useful for matching multiple values in the same field.
query: {
$and: [
{ notes: { $match: 'javascript' } },
{ notes: { $match: 'project' } }
]
}Shorthand for equality:
// Long form
query: {
$and: [
{ tags: 'javascript' },
{ tags: 'react' }
]
}
// Shorthand
query: {
tags: ['javascript', 'react']
}Example:
// Find articles tagged with both "javascript" AND "react"
const articles = await service.find({
query: {
tags: ['javascript', 'react']
}
});
// More complex: articles that mention both "javascript" and "tutorial" in content
const tutorials = await service.find({
query: {
$and: [
{ content: { $match: 'javascript' } },
{ content: { $match: 'tutorial' } }
]
}
});simple_query_string query - A query that uses the SimpleQueryParser to parse its context.
query: {
$sqs: {
$fields: ['title^5', 'description'],
$query: '+like +javascript',
$operator: 'and' // Optional, default: 'or'
}
}Parameters:
$fields- Array of fields to search. Use^to boost field importance (e.g.,title^5)$query- The query string with operators$operator- Default operator:'and'or'or'(default:'or')
Query string operators:
+- AND operator (must match)|- OR operator-- NOT operator (must not match)"..."- Phrase query*- Wildcard(...)- Grouping
Example:
// Search for articles that mention "javascript" AND "react" in title or content
// Boost title matches 5x
const articles = await service.find({
query: {
$sqs: {
$fields: ['title^5', 'content'],
$query: '+javascript +react',
$operator: 'and'
}
}
});
// URL format
// http://localhost:3030/articles?$sqs[$fields][]=title^5&$sqs[$fields][]=content&$sqs[$query]=+javascript +react&$sqs[$operator]=andhas_child query - Find all documents which have children matching the query.
The $child query is a full-blown query of its own and requires the $type property.
Elasticsearch 6.0+ Change:
- Before 6.0:
$typerepresents the child document type in the index - 6.0+:
$typerepresents the child relationship name as defined in the join field
query: {
$child: {
$type: 'blog_tag',
tag: 'something'
}
}Example:
// Find all blog posts that have a comment containing "great"
const posts = await service.find({
query: {
$child: {
$type: 'comment',
content: { $match: 'great' }
}
}
});
// Find all posts with active comments
const postsWithActiveComments = await service.find({
query: {
$child: {
$type: 'comment',
status: 'active'
}
}
});See Parent-Child Relationships for more details.
has_parent query - Find all documents which have a parent matching the query.
The $parent query is a full-blown query of its own and requires the $type property.
Elasticsearch 6.0+ Change:
- Before 6.0:
$typerepresents the parent document type in the index - 6.0+:
$typerepresents the parent relationship name as defined in the join field
query: {
$parent: {
$type: 'blog',
title: {
$match: 'javascript'
}
}
}Example:
// Find all comments whose parent blog post has "javascript" in the title
const comments = await service.find({
query: {
$parent: {
$type: 'blog',
title: { $match: 'javascript' }
}
}
});
// Find all comments on published posts
const commentsOnPublished = await service.find({
query: {
$parent: {
$type: 'blog',
status: 'published'
}
}
});See Parent-Child Relationships for more details.
// Find active articles about "javascript" or "react" with high priority
const articles = await service.find({
query: {
status: 'active',
priority: { $gte: 8 },
$or: [
{ tags: 'javascript' },
{ tags: 'react' }
],
$sort: {
createdAt: -1
},
$limit: 20
}
});// Search for "machine learning" in content, only in published articles
const articles = await service.find({
query: {
status: 'published',
content: { $match: 'machine learning' },
publishedAt: { $gte: '2024-01-01' },
$sort: {
_score: -1 // Sort by relevance
}
}
});// Complex search with field boosting
const results = await service.find({
query: {
$sqs: {
$fields: ['title^10', 'tags^5', 'content'],
$query: '+javascript +(react | vue) -angular',
$operator: 'and'
},
status: 'published',
$limit: 50
}
});// Find articles with both "javascript" and "tutorial" tags
const tutorials = await service.find({
query: {
$and: [
{ tags: 'javascript' },
{ tags: 'tutorial' }
]
}
});
// Or using shorthand
const tutorials = await service.find({
query: {
tags: ['javascript', 'tutorial']
}
});// Find complete user profiles (have all required fields)
const completeProfiles = await service.find({
query: {
$exists: ['email', 'phone', 'address', 'avatar']
}
});
// Find incomplete profiles (missing optional fields)
const incompleteProfiles = await service.find({
query: {
$missing: ['phone', 'address']
}
});// Find users with email addresses from specific domains
const users = await service.find({
query: {
email: { $wildcard: '*@company.com' }
}
});
// Find product codes matching a pattern
const products = await service.find({
query: {
sku: { $regexp: 'PROD-[0-9]{4}-[A-Z]{2}' }
}
});- Use specific queries - Prefer
$matchover$wildcardwhen possible - Limit result sets - Always use
$limitto prevent large result sets - Use filters for exact matches - Use equality queries for exact matches instead of full-text search
- Avoid leading wildcards - Queries like
$wildcard: '*abc'are slow - Use pagination - Use
$skipand$limitfor large result sets - Index fields properly - Ensure fields are indexed appropriately for your query types
Some query operators can be restricted for security. See Configuration for details on:
whitelist- Control which query operators are allowedsecurity.maxQueryDepth- Limit query nesting depthsecurity.maxArraySize- Limit array sizes in$inand$ninsecurity.maxQueryStringLength- Limit$sqsquery lengthsecurity.searchableFields- Restrict searchable fields for$sqs
- Configure query security: Configuration
- Learn about parent-child queries: Parent-Child Relationships
- Optimize query performance: Performance Features