8000 feathers-elasticsearch/docs/querying.md at main · feathersjs/feathers-elasticsearch · GitHub
[go: up one dir, main page]

Skip to content 10000

Latest commit

 

History

History
652 lines (522 loc) · 13.4 KB

File metadata and controls

652 lines (522 loc) · 13.4 KB

Querying

feathers-elasticsearch supports both standard Feathers query syntax and Elasticsearch-specific queries.

Standard Feathers Queries

All standard Feathers query operators are supported:

Equality

// Find messages with text equal to "Hello"
query: {
  text: 'Hello'
}

Comparison Operators

// $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' }
}

Array Operators

// $in - value in array
query: {
  status: { $in: ['active', 'pending'] }
}

// $nin - value not in array
query: {
  status: { $nin: ['archived', 'deleted'] }
}

Special Operators

// $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']
}

Elasticsearch-Specific Queries

On top of standard Feathers queries, feathers-elasticsearch supports Elasticsearch-specific query operators.

$all

match_all query - Find all documents.

query: {
  $all: true
}

Example:

// Find all messages
const allMessages = await service.find({
  query: { $all: true }
});

$prefix

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

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

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

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']
  }
});

$missing

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

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.

$phrase

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' }
  }
});

$phrase_prefix

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' }
  }
});

$and

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' } }
    ]
  }
});

$sqs

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]=and

$child

has_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: $type represents the child document type in the index
  • 6.0+: $type represents 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.


$parent

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: $type represents the parent document type in the index
  • 6.0+: $type represents 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.


Complex Query Examples

Combining Multiple Operators

// 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
  }
});

Full-Text Search with Filters

// 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
    }
  }
});

Advanced Text Search

// 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
  }
});

Array Field Matching

// 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']
  }
});

Existence Checks

// 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']
  }
});

Pattern Matching

// 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}' }
  }
});

Query Performance Tips

  1. Use specific queries - Prefer $match over $wildcard when possible
  2. Limit result sets - Always use $limit to prevent large result sets
  3. Use filters for exact matches - Use equality queries for exact matches instead of full-text search
  4. Avoid leading wildcards - Queries like $wildcard: '*abc' are slow
  5. Use pagination - Use $skip and $limit for large result sets
  6. Index fields properly - Ensure fields are indexed appropriately for your query types

Security Considerations

Some query operators can be restricted for security. See Configuration for details on:

  • whitelist - Control which query operators are allowed
  • security.maxQueryDepth - Limit query nesting depth
  • security.maxArraySize - Limit array sizes in $in and $nin
  • security.maxQueryStringLength - Limit $sqs query length
  • security.searchableFields - Restrict searchable fields for $sqs

Next Steps

0