Search For Service

Streamline Search For Service automation and seamless integration

Search For Service is a community skill for implementing service discovery and search functionality, covering full-text search, faceted filtering, geolocation queries, relevance ranking, and search result presentation patterns.

What Is This?

Overview

Search For Service provides patterns for building service discovery features in marketplace and directory applications. It covers full-text search with tokenization, stemming, and fuzzy matching for natural language queries, faceted filtering by category, price range, rating, and availability, geolocation queries that find services within a specified radius from the user, relevance ranking that combines text match scores with popularity and proximity signals, and search result presentation with pagination, sorting, and highlight snippets. The skill enables developers to build discoverable service listings that connect users with relevant providers.

Who Should Use This

This skill serves developers building service marketplace platforms with provider search, teams implementing directory applications with location-based discovery, and engineers adding search functionality to listing platforms.

Why Use It?

Problems It Solves

Simple database queries cannot handle fuzzy text matching or relevance scoring for service discovery. Location-based search requires geospatial indexing that relational databases handle poorly without extensions. Combining multiple filter dimensions with text search needs efficient query composition. Paginating large result sets while maintaining consistent sort order demands cursor-based approaches.

Core Highlights

Full-text engine indexes service descriptions for fast keyword matching. Geospatial queries filter services by distance from a coordinate point. Facet aggregations compute filter counts for category and attribute breakdown. Relevance scorer combines text match with rating and distance signals.

How to Use It?

Basic Usage

import { Client } from
  '@elastic/elasticsearch';

const es = new Client({
  node: process.env.ES_URL });

async function searchServices(
  query: string,
  filters: {
    category?: string;
    minRating?: number;
    maxPrice?: number;
  }
) {
  const must: object[] = [];
  const filter: object[] = [];

  if (query) {
    must.push({
      multi_match: {
        query,
        fields: [
          'title^3',
          'description',
          'tags^2'],
        fuzziness: 'AUTO',
      },
    });
  }

  if (filters.category) {
    filter.push({ term:
      { category:
        filters.category } });
  }
  if (filters.minRating) {
    filter.push({ range:
      { rating: { gte:
        filters.minRating } } });
  }
  if (filters.maxPrice) {
    filter.push({ range:
      { price: { lte:
        filters.maxPrice } } });
  }

  const result = await es.search({
    index: 'services',
    body: {
      query: { bool:
        { must, filter } },
      highlight: { fields:
        { description: {} } },
    },
  });

  return result.hits.hits.map(
    (h) => ({
      ...h._source,
      score: h._score,
      highlights:
        h.highlight,
    }));
}

Real-World Examples

// Geolocation service search
async function searchNearby(
  lat: number,
  lon: number,
  radiusKm: number,
  query?: string
) {
  const must: object[] = [];
  if (query) {
    must.push({ multi_match: {
      query,
      fields: ['title^2',
        'description'],
    } });
  }

  const result = await es.search({
    index: 'services',
    body: {
      query: {
        bool: {
          must,
          filter: [{
            geo_distance: {
              distance:
                `${radiusKm}km`,
              location:
                { lat, lon },
            },
          }],
        },
      },
      sort: [{
        _geo_distance: {
          location:
            { lat, lon },
          order: 'asc',
          unit: 'km',
        },
      }],
      aggs: {
        categories: {
          terms: {
            field: 'category',
            size: 20 },
        },
        avg_rating: {
          avg: {
            field: 'rating' },
        },
      },
    },
  });

  return {
    services:
      result.hits.hits.map(
        (h: any) => ({
          ...h._source,
          distance:
            h.sort?.[0],
        })),
    facets:
      result.aggregations,
  };
}

Advanced Tips

Use function_score queries to boost results by rating, recency, or provider verification status for better relevance. Implement search-as-you-type with completion suggesters for instant results. Cache frequently used filter combinations to reduce search latency for popular queries.

When to Use It?

Use Cases

Build a local services marketplace where users find providers by location and specialty. Create a freelancer directory with skill-based search and availability filtering. Implement a booking platform with date-based availability search.

Related Topics

Elasticsearch, full-text search, geospatial queries, faceted navigation, and search relevance.

Important Notes

Requirements

A search engine such as Elasticsearch or Typesense for full-text and geospatial indexing. Database synchronization for keeping the search index updated. Geocoding service for converting addresses to coordinates.

Usage Recommendations

Do: use field boosting to prioritize title matches over description matches for better relevance. Index service locations as geo_point fields for distance calculations. Return facet counts alongside results for filter UI.

Don't: rely on database LIKE queries for service search when a dedicated search engine handles relevance and performance better. Skip pagination which returns unbounded result sets. Reindex the entire dataset for single-document updates when partial updates are supported.

Limitations

Search engines require separate infrastructure and index synchronization with the primary database. Relevance tuning needs iterative testing with real query patterns. Geospatial search accuracy depends on the quality of location data stored in the index.