← Назад к вопросам
Что такое полнотекстовый поиск?
1.7 Middle🔥 121 комментариев
#DevOps и инфраструктура#Django
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Полнотекстовый поиск
Полнотекстовый поиск (Full-Text Search, FTS) — это специализированная техника поиска в больших текстовых документах или базах данных, которая позволяет находить документы по отдельным словам или фразам, а не по точному совпадению всей строки.
Основное отличие от обычного LIKE
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title TEXT,
content TEXT
)
''')
cursor.executemany('INSERT INTO articles VALUES (?, ?, ?)', [
(1, 'Python Programming', 'Learn Python basics and advanced concepts'),
(2, 'Web Development', 'Build websites with Django and Flask'),
(3, 'Data Science', 'Python for data analysis and machine learning'),
])
conn.commit()
# 1. Обычный LIKE — ищет по строке целиком (медленно)
print("LIKE поиск:")
result = cursor.execute(
"SELECT * FROM articles WHERE content LIKE '%Python%'"
).fetchall()
for row in result:
print(row)
# 2. Полнотекстовый поиск — быстрее и умнее
print("\nПолнотекстовый поиск (нужна индексация):")
Как работает FTS
1. Индексирование текста
- Текст разбивается на токены (слова)
- Убираются стоп-слова (и, или, а, the, a)
- Применяется стемминг (приведение к корню: "программирование" → "программ")
- Создаётся обратный индекс: слово → список документов
2. Поиск
- Запрос также разбивается на токены
- Ищются совпадения в индексе (очень быстро)
- Результаты ранжируются по релевантности
SQLite FTS5
import sqlite3
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# Создаём таблицу с полнотекстовым поиском
cursor.execute('''
CREATE VIRTUAL TABLE articles_fts USING fts5(
title,
content,
content='articles',
content_rowid='id'
)
''')
# Заполняем индекс
cursor.executemany(
'INSERT INTO articles_fts(rowid, title, content) VALUES (?, ?, ?)',
[
(1, 'Python Programming', 'Learn Python basics and advanced concepts'),
(2, 'Web Development', 'Build websites with Django and Flask'),
(3, 'Data Science', 'Python for data analysis and machine learning'),
]
)
conn.commit()
# Поиск
print("FTS поиск по одному слову:")
result = cursor.execute(
"SELECT title, content FROM articles_fts WHERE articles_fts MATCH 'python'"
).fetchall()
for row in result:
print(row)
# Поиск по фразе
print("\nПоиск по фразе:")
result = cursor.execute(
'SELECT title FROM articles_fts WHERE articles_fts MATCH \'"data analysis"\' '
).fetchall()
for row in result:
print(row)
# С ранжированием по релевантности
print("\nС ранжированием:")
result = cursor.execute('''
SELECT title, rank FROM articles_fts
WHERE articles_fts MATCH 'python'
ORDER BY rank
''').fetchall()
for row in result:
print(row)
PostgreSQL Full-Text Search
from sqlalchemy import create_engine, text
engine = create_engine('postgresql://...')
with engine.connect() as conn:
# Создаём tsvector (токенизированный вектор)
conn.execute(text('''
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
body TEXT,
search_vector tsvector
)
'''))
# Заполняем индекс
conn.execute(text('''
INSERT INTO documents (title, body, search_vector) VALUES
('Python Guide', 'Learn Python programming',
to_tsvector('english', 'Learn Python programming'))
'''))
conn.commit()
# Поиск с оператором @@
result = conn.execute(text(
"SELECT title FROM documents WHERE search_vector @@ to_tsquery('english', 'python')"
)).fetchall()
for row in result:
print(row)
Elasticsearch для масштабного FTS
from elasticsearch import Elasticsearch
es = Elasticsearch(['http://localhost:9200'])
# Индексирование
es.index(index='articles', id=1, body={
'title': 'Python Programming',
'content': 'Learn Python basics and advanced concepts'
})
es.index(index='articles', id=2, body={
'title': 'Web Development',
'content': 'Build websites with Django and Flask'
})
# Поиск
results = es.search(index='articles', body={
'query': {
'multi_match': {
'query': 'python',
'fields': ['title^2', 'content'] # title важнее
}
}
})
for hit in results['hits']['hits']:
print(f"Score: {hit['_score']}, Title: {hit['_source']['title']}")
Сравнение методов
| Метод | Скорость | Масштаб | Сложность | Языки |
|---|---|---|---|---|
| LIKE | Медленно | <100K | Просто | SQL |
| SQLite FTS5 | Быстро | До 1M | Средне | SQLite |
| PostgreSQL FTS | Быстро | До 10M | Средне | PostgreSQL |
| Elasticsearch | Очень быстро | Млрд+ | Сложно | Специальный |
Стемминг и нормализация
import nltk
from nltk.stem import SnowballStemmer
# Скачиваем ресурсы
nltk.download('punkt')
stemmer = SnowballStemmer('english')
words = ['programming', 'programs', 'programmer', 'programmed']
for word in words:
print(f"{word} → {stemmer.stem(word)}")
# Вывод:
# programming → program
# programs → program
# programmer → program
# programmed → program
Лучшие практики FTS
-
Выбирай правильный движок
- Малый объём (<100K) → SQLite FTS5
- Средний объём (100K-10M) → PostgreSQL FTS
- Большой объём (>10M) → Elasticsearch/OpenSearch
-
Оптимизируй стемминг и стоп-слова
# PostgreSQL SELECT * FROM articles WHERE search_vector @@ to_tsquery('english', 'python & web') -
Кэшируй часто используемые поиски (Redis)
-
Мониторь производительность через размер индекса
-
Используй ранжирование для релевантности результатов
Полнотекстовый поиск критичен для любого приложения с большим объёмом текстовых данных. Выбор между SQLite, PostgreSQL и Elasticsearch зависит от масштаба и требований к производительности.