🗄️ Database

Elasticsearch Search Engine

Last updated: 2025-09-25 02:29:54

Elasticsearch Full-Text Search

Elasticsearch is a distributed search and analytics engine built on Apache Lucene.

Basic Elasticsearch Operations

// Node.js client setup
const { Client } = require('@elastic/elasticsearch');

const client = new Client({
  node: 'http://localhost:9200',
  auth: {
    username: 'elastic',
    password: 'password'
  }
});

// Create an index
async function createIndex(indexName) {
  try {
    await client.indices.create({
      index: indexName,
      body: {
        mappings: {
          properties: {
            title: {
              type: 'text',
              analyzer: 'standard'
            },
            content: {
              type: 'text',
              analyzer: 'standard'
            },
            author: {
              type: 'keyword'
            },
            publishDate: {
              type: 'date'
            },
            tags: {
              type: 'keyword'
            },
            category: {
              type: 'keyword'
            }
          }
        }
      }
    });
  } catch (error) {
    console.error('Error creating index:', error);
  }
}

// Index a document
async function indexDocument(indexName, document) {
  try {
    const response = await client.index({
      index: indexName,
      body: document
    });
    return response.body._id;
  } catch (error) {
    console.error('Error indexing document:', error);
  }
}

Search Queries

// Basic search
async function basicSearch(indexName, query) {
  try {
    const response = await client.search({
      index: indexName,
      body: {
        query: {
          match: {
            title: query
          }
        }
      }
    });
    return response.body.hits;
  } catch (error) {
    console.error('Error searching:', error);
  }
}

// Advanced search with filters
async function advancedSearch(indexName, searchParams) {
  const {
    query,
    category,
    author,
    dateFrom,
    dateTo,
    tags,
    size = 10,
    from = 0
  } = searchParams;
  
  const searchBody = {
    query: {
      bool: {
        must: [],
        filter: []
      }
    },
    sort: [
      { publishDate: { order: 'desc' } },
      '_score'
    ],
    size,
    from
  };
  
  // Add text search
  if (query) {
    searchBody.query.bool.must.push({
      multi_match: {
        query,
        fields: ['title^2', 'content'],
        type: 'best_fields',
        fuzziness: 'AUTO'
      }
    });
  }
  
  // Add filters
  if (category) {
    searchBody.query.bool.filter.push({
      term: { category }
    });
  }
  
  if (author) {
    searchBody.query.bool.filter.push({
      term: { author }
    });
  }
  
  if (dateFrom || dateTo) {
    const dateRange = {};
    if (dateFrom) dateRange.gte = dateFrom;
    if (dateTo) dateRange.lte = dateTo;
    
    searchBody.query.bool.filter.push({
      range: { publishDate: dateRange }
    });
  }
  
  if (tags && tags.length > 0) {
    searchBody.query.bool.filter.push({
      terms: { tags }
    });
  }
  
  try {
    const response = await client.search({
      index: indexName,
      body: searchBody
    });
    return response.body;
  } catch (error) {
    console.error('Error in advanced search:', error);
  }
}

Aggregations and Analytics

// Aggregations for analytics
async function getAnalytics(indexName) {
  try {
    const response = await client.search({
      index: indexName,
      body: {
        size: 0, // Don't return documents, just aggregations
        aggs: {
          categories: {
            terms: {
              field: 'category',
              size: 10
            }
          },
          authors: {
            terms: {
              field: 'author',
              size: 10
            }
          },
          posts_over_time: {
            date_histogram: {
              field: 'publishDate',
              calendar_interval: 'month'
            }
          },
          popular_tags: {
            terms: {
              field: 'tags',
              size: 20
            }
          },
          avg_posts_per_author: {
            avg: {
              script: {
                source: '1' // Each document represents one post
              }
            }
          }
        }
      }
    });
    
    return response.body.aggregations;
  } catch (error) {
    console.error('Error getting analytics:', error);
  }
}

// Search suggestions
async function getSearchSuggestions(indexName, prefix) {
  try {
    const response = await client.search({
      index: indexName,
      body: {
        suggest: {
          title_suggest: {
            prefix,
            completion: {
              field: 'title_suggest',
              size: 5
            }
          }
        }
      }
    });
    
    return response.body.suggest.title_suggest[0].options;
  } catch (error) {
    console.error('Error getting suggestions:', error);
  }
}

Bulk Operations

// Bulk indexing
async function bulkIndex(indexName, documents) {
  const body = [];
  
  documents.forEach(doc => {
    body.push({
      index: {
        _index: indexName,
        _id: doc.id
      }
    });
    body.push(doc);
  });
  
  try {
    const response = await client.bulk({
      refresh: true,
      body
    });
    
    if (response.body.errors) {
      console.error('Bulk indexing errors:', response.body.items);
    }
    
    return response.body;
  } catch (error) {
    console.error('Bulk indexing error:', error);
  }
}

// Update documents
async function updateDocument(indexName, documentId, updates) {
  try {
    const response = await client.update({
      index: indexName,
      id: documentId,
      body: {
        doc: updates,
        doc_as_upsert: true
      }
    });
    return response.body;
  } catch (error) {
    console.error('Error updating document:', error);
  }
}

// Delete documents by query
async function deleteByQuery(indexName, query) {
  try {
    const response = await client.deleteByQuery({
      index: indexName,
      body: {
        query
      }
    });
    return response.body;
  } catch (error) {
    console.error('Error deleting documents:', error);
  }
}