Какие знаешь инструменты поиска по словам?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Инструменты поиска по словам (Full-Text Search)
Основные инструменты поиска
Для реализации полнотекстового поиска (full-text search) есть несколько популярных решений с разными характеристиками:
1. Elasticsearch — самый популярный
Elasticsearch — это распределённая поисковая система на основе Lucene. Стандарт для полнотекстового поиска:
from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
# Подключение
es = Elasticsearch(['http://localhost:9200'])
# Создание индекса с анализатором
es.indices.create(index='articles', body={
'settings': {
'analysis': {
'analyzer': {
'russian_analyzer': {
'type': 'standard',
'stopwords': '_russian_'
}
}
}
},
'mappings': {
'properties': {
'title': {'type': 'text', 'analyzer': 'russian_analyzer'},
'content': {'type': 'text', 'analyzer': 'russian_analyzer'},
'tags': {'type': 'keyword'},
'created_at': {'type': 'date'}
}
}
})
# Индексирование документов
documents = [
{'_index': 'articles', '_id': 1, 'title': 'Python для начинающих', 'content': 'Изучение Python', 'tags': ['python', 'tutorial']},
{'_index': 'articles', '_id': 2, 'title': 'Django веб-фреймворк', 'content': 'Создание веб-приложений', 'tags': ['django', 'web']},
]
bulk(es, documents)
# Поиск по словам
query = {
'query': {
'multi_match': {
'query': 'Python Django', # Поиск по нескольким полям
'fields': ['title^2', 'content'], # title важнее (boost=2)
'operator': 'and' # Все слова должны совпадать
}
},
'highlight': {
'fields': {
'title': {},
'content': {}
}
}
}
results = es.search(index='articles', body=query)
for hit in results['hits']['hits']:
print(f'Score: {hit["_score"]}')
print(f'Title: {hit["_source"]["title"]}')
if 'highlight' in hit:
print(f'Highlighted: {hit["highlight"]}')
# Фильтрация с поиском
query_filtered = {
'query': {
'bool': {
'must': [
{'multi_match': {'query': 'Python', 'fields': ['title', 'content']}}
],
'filter': [
{'term': {'tags': 'python'}},
{'range': {'created_at': {'gte': '2024-01-01'}}}
]
}
}
}
# Faceted search (получить категории)
faceted_query = {
'query': {'match_all': {}},
'aggs': {
'tags': {
'terms': {'field': 'tags', 'size': 10}
},
'by_date': {
'date_histogram': {'field': 'created_at', 'interval': 'month'}
}
}
}
Преимущества:
- Очень быстро
- Развитая экосистема
- Масштабируемость
- Faceting, suggest, autocomplete
- RESTful API
Недостатки:
- Требует отдельного сервера
- Сложная настройка
- Память и CPU потребление
2. PostgreSQL Full Text Search
PostgreSQL встроенный полнотекстовый поиск — простое решение для средних объёмов:
import psycopg2
from datetime import datetime
conn = psycopg2.connect(
host='localhost',
database='myapp',
user='postgres'
)
cursor = conn.cursor()
# Создание таблицы с полнотекстовым индексом
cursor.execute('''
CREATE TABLE IF NOT EXISTS articles (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
search_vector tsvector GENERATED ALWAYS AS (
to_tsvector('russian', title) || to_tsvector('russian', content)
) STORED
);
-- Индекс для быстрого поиска
CREATE INDEX IF NOT EXISTS articles_search_idx ON articles USING GIN (search_vector);
''')
# Вставка данных
cursor.execute('''
INSERT INTO articles (title, content) VALUES
(%s, %s)
''', ('Python для начинающих', 'Изучение Python и её основ'))
conn.commit()
# Поиск по словам
search_query = 'Python'
cursor.execute(f'''
SELECT id, title,
ts_rank(search_vector, query) as relevance,
ts_headline('russian', content, query, 'HighlightAll=true') as snippet
FROM articles,
plainto_tsquery('russian', %s) as query
WHERE search_vector @@ query
ORDER BY relevance DESC
LIMIT 10
''', (search_query,))
for row in cursor.fetchall():
print(f'ID: {row[0]}')
print(f'Title: {row[1]}')
print(f'Relevance: {row[2]}')
print(f'Snippet: {row[3]}')
# Поиск с повышением релевантности
cursor.execute('''
SELECT id, title,
ts_rank(search_vector, query) *
CASE WHEN title @@ query THEN 1.5 ELSE 1 END as relevance
FROM articles,
plainto_tsquery('russian', %s) as query
WHERE search_vector @@ query
ORDER BY relevance DESC
''', ('Python',))
conn.close()
Преимущества:
- Встроено в PostgreSQL
- Нет дополнительной инфраструктуры
- Достаточно быстро
- Хорошо для русского языка
Недостатки:
- Медленнее Elasticsearch
- Ограниченные возможности (нет fuzzy, но есть)
- Нельзя масштабировать за пределы одного сервера
3. Apache Solr
Apache Solr — альтернатива Elasticsearch, также на основе Lucene:
import requests
import json
solr_url = 'http://localhost:8983/solr'
# Индексирование документа
doc = {
'id': '1',
'title': 'Python для начинающих',
'content': 'Изучение Python',
'category': 'python'
}
response = requests.post(
f'{solr_url}/articles/update?commit=true',
json={'add': {'doc': doc}},
headers={'Content-Type': 'application/json'}
)
# Поиск
params = {
'q': 'title:Python', # Поиск в поле title
'rows': 10,
'sort': 'score desc',
'hl': 'true', # Highlighting
'hl.fl': 'title,content' # Какие поля выделять
}
response = requests.get(f'{solr_url}/articles/select', params=params)
results = response.json()
for doc in results['response']['docs']:
print(f'Score: {doc.get("score")}')
print(f'Title: {doc["title"]}')
Преимущества:
- Похож на Elasticsearch
- Стабилен
- Хорошо для энтерпрайза
Недостатки:
- Менее популярен чем Elasticsearch
- Медленнее индексирует
4. meilisearch — быстрый и простой
MeiliSearch — современный поисковик с акцентом на простоту и скорость:
import meilisearch
# Подключение
client = meilisearch.Client('http://localhost:7700', 'your-master-key')
# Создание индекса
index = client.create_index('articles', {'primaryKey': 'id'})
# Индексирование
documents = [
{'id': 1, 'title': 'Python для начинающих', 'content': 'Изучение'},
{'id': 2, 'title': 'Django веб-фреймворк', 'content': 'Создание сайтов'},
]
index.add_documents(documents)
# Поиск
results = index.search('Python')
print(f'Found {results["nbHits"]} results')
for hit in results['hits']:
print(f'Title: {hit["title"]}')
# Advanced search
advanced = index.search(
'Python',
{
'limit': 10,
'offset': 0,
'facets': ['category'], # Фасеты
'attributesToHighlight': ['title', 'content'],
}
)
Преимущества:
- Очень просто использовать
- Быстро работает
- Автоматический typo tolerant
- REST API
Недостатки:
- Менее гибкий чем Elasticsearch
- Меньше возможностей
5. SQLite с FTS5
SQLite FTS5 — встроенный полнотекстовый поиск для SQLite:
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# Создание таблицы с FTS5
cursor.execute('''
CREATE VIRTUAL TABLE articles USING fts5(
title,
content
);
''')
# Индексирование
cursor.execute("INSERT INTO articles VALUES (?, ?)",
('Python для начинающих', 'Изучение Python')
)
cursor.execute("INSERT INTO articles VALUES (?, ?)",
('Django веб-фреймворк', 'Создание веб-приложений')
)
# Поиск
cursor.execute('''
SELECT title, rank
FROM articles
WHERE articles MATCH 'Python'
ORDER BY rank
''')
for title, rank in cursor.fetchall():
print(f'Title: {title}, Relevance: {rank}')
# Фраза и AND/OR
cursor.execute('''
SELECT title
FROM articles
WHERE articles MATCH 'Python AND web'
''')
conn.close()
Преимущества:
- Встроено в SQLite
- Нет дополнительных сервисов
- Достаточно быстро
Недостатки:
- Медленнее чем специализированные
- Ограниченные возможности
Сравнение инструментов
| Инструмент | Скорость | Простота | Масштабируемость | Когда использовать |
|---|---|---|---|---|
| Elasticsearch | ⚡⚡⚡ | ⭐⭐ | ⭐⭐⭐ | Большие проекты, high-load |
| PostgreSQL FTS | ⚡⚡ | ⭐⭐⭐ | ⭐⭐ | Средние объёмы, простые требования |
| Apache Solr | ⚡⚡⭐ | ⭐⭐ | ⭐⭐⭐ | Enterprise, стабильность |
| MeiliSearch | ⚡⚡⭐ | ⭐⭐⭐ | ⭐⭐ | Стартапы, simple search |
| SQLite FTS5 | ⚡ | ⭐⭐⭐ | ⭐ | Маленькие приложения |
Best Practices
✅ Используй Elasticsearch для production с высокими требованиями ✅ Используй PostgreSQL FTS для среднего масштаба ✅ Используй MeiliSearch для быстрого прототипирования ✅ Индексируй в фоне через Celery/RQ ✅ Синхронизируй данные между основной БД и поисковиком ✅ Используй boost для важных полей (title важнее content) ✅ Кэшируй популярные запросы в Redis
Архитектура поиска
PostgreSQL (основная БД)
↓
Celery Task (индексирование)
↓
Elasticsearch (индекс поиска)
↓
REST API (поиск)
↓
Frontend (результаты с highlight)
Выбор инструмента зависит от масштаба, требований к скорости и сложности логики поиска.