Skip to content

Commit 710f664

Browse files
committed
fix search
1 parent 27fa3c2 commit 710f664

7 files changed

Lines changed: 65 additions & 22 deletions

File tree

Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,23 @@ tags:
142142

143143
assign:
144144
$(PYTHON) manage.py assign_tags_to_books
145+
146+
# ======================
147+
# ELASTICSEARCH
148+
# ======================
149+
.PHONY: elastic-create elastic-delete elastic-populate elastic-rebuild elastic-status
150+
151+
elastic-create: ## Create Elasticsearch indices
152+
$(PYTHON) manage.py search_index --create
153+
154+
elastic-delete: ## Delete Elasticsearch indices
155+
$(PYTHON) manage.py search_index --delete --force
156+
157+
elastic-populate: ## Populate Elasticsearch indices
158+
$(PYTHON) manage.py search_index --populate
159+
160+
elastic-rebuild: elastic-delete elastic-create elastic-populate ## Rebuild Elasticsearch indices (delete, create, populate)
161+
@echo "Elasticsearch indices rebuilt successfully"
162+
163+
elastic-status: ## Show Elasticsearch indices status
164+
$(PYTHON) manage.py search_index --status

apps/books/api/v1/book_elastic_views.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ class BookDocumentView(DocumentViewSet):
3434

3535
# Поля для полнотекстового поиска
3636
search_fields = {
37-
"title": {"boost": 4, "analyzer": "standard"},
38-
"description": {"boost": 2, "analyzer": "standard"},
39-
"author.first_name": {"boost": 3, "analyzer": "standard"},
40-
"author.last_name": {"boost": 3, "analyzer": "standard"},
41-
"publisher.name": {"boost": 1, "analyzer": "standard"},
42-
"tags.name": {"boost": 1, "analyzer": "standard"},
37+
"title": {"boost": 4, "fuzziness": 1, "prefix_length": 0},
38+
"description": {"boost": 2, "fuzziness": 1, "prefix_length": 0},
39+
"author.first_name": {"boost": 3, "fuzziness": 1, "prefix_length": 0},
40+
"author.last_name": {"boost": 3, "fuzziness": 1, "prefix_length": 0},
41+
"publisher.name": {"boost": 1, "fuzziness": 1, "prefix_length": 0},
42+
"tags.name": {"boost": 1, "fuzziness": 1, "prefix_length": 0},
4343
}
4444

4545
# Поля для точной фильтрации

frontend/src/components/BooksList.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ interface BooksListProps {
1212
onBookClick: (book: Book) => void;
1313
enableLazyLoading?: boolean;
1414
enableInfiniteScroll?: boolean;
15+
searchQuery?: string;
1516
}
1617

17-
export default function BooksList({
18-
onBookClick,
19-
enableLazyLoading = true,
20-
enableInfiniteScroll = true
18+
export default function BooksList({
19+
onBookClick,
20+
enableLazyLoading = true,
21+
enableInfiniteScroll = true,
22+
searchQuery = ''
2123
}: BooksListProps) {
2224
const [books, setBooks] = useState<Book[]>([]);
2325
const [authors, setAuthors] = useState<Author[]>([]);
@@ -54,7 +56,10 @@ export default function BooksList({
5456
if (filters.publisher) params.publisher = filters.publisher;
5557
if (filters.ordering) params.ordering = filters.ordering;
5658

57-
const response = await booksApi.getBooks(params);
59+
// Use search API if there's a non-empty search query, otherwise use regular books API
60+
const response = searchQuery && searchQuery.trim()
61+
? await booksApi.searchBooks({ ...params, search: searchQuery.trim() })
62+
: await booksApi.getBooks(params);
5863

5964
if (isLoadMore) {
6065
setBooks(prev => [...prev, ...response.results]);
@@ -95,7 +100,7 @@ export default function BooksList({
95100

96101
useEffect(() => {
97102
loadBooks();
98-
}, [filters.author, filters.category, filters.publisher, filters.ordering]);
103+
}, [filters.author, filters.category, filters.publisher, filters.ordering, searchQuery]);
99104

100105
const handleAuthorChange = (author: string) => {
101106
const authorValue = author === 'all' ? '' : author;

frontend/src/components/Layout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ import {
1212
interface LayoutProps {
1313
children: React.ReactNode;
1414
onSearch?: (query: string) => void;
15+
searchQuery?: string;
16+
onSearchQueryChange?: (query: string) => void;
1517
}
1618

17-
export default function Layout({ children, onSearch }: LayoutProps) {
18-
const [searchQuery, setSearchQuery] = useState('');
19+
export default function Layout({ children, onSearch, searchQuery = '', onSearchQueryChange }: LayoutProps) {
1920
const [isDark, setIsDark] = useState(false);
2021

2122
const handleSearch = (e: React.FormEvent) => {
@@ -45,7 +46,7 @@ export default function Layout({ children, onSearch }: LayoutProps) {
4546
type="text"
4647
placeholder="Поиск книг..."
4748
value={searchQuery}
48-
onChange={(e) => setSearchQuery(e.target.value)}
49+
onChange={(e) => onSearchQueryChange?.(e.target.value)}
4950
className="w-64"
5051
/>
5152
<Button type="submit" size="sm">

frontend/src/lib/api.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import axios from 'axios';
22
import type { Author, Book, Publisher, Tag, PaginatedResponse } from '@/types';
33

4-
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1';
4+
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8001/api/v1';
55

66
const api = axios.create({
77
baseURL: API_BASE_URL,
@@ -22,6 +22,18 @@ export const booksApi = {
2222
return response.data;
2323
},
2424

25+
searchBooks: async (params?: {
26+
search?: string;
27+
author?: string;
28+
tag?: string;
29+
publisher?: string;
30+
ordering?: string;
31+
page?: number;
32+
}): Promise<PaginatedResponse<Book>> => {
33+
const response = await api.get('/search/', { params });
34+
return response.data;
35+
},
36+
2537
getBook: async (id: number): Promise<Book> => {
2638
const response = await api.get(`/books/${id}/`);
2739
return response.data;

frontend/src/pages/HomePage.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useState } from 'react';
12
import { useNavigate } from 'react-router-dom';
23
import Layout from '@/components/Layout';
34
import BooksList from '@/components/BooksList';
@@ -6,18 +7,22 @@ import type { Book } from '@/types';
67

78
export default function HomePage() {
89
const navigate = useNavigate();
9-
10+
const [searchQuery, setSearchQuery] = useState('');
11+
1012
const handleBookClick = (book: Book) => {
1113
navigate(`/book/${book.id}`);
1214
};
1315

1416
const handleSearch = (query: string) => {
15-
// This will be handled by the BooksList component
16-
console.log('Search query:', query);
17+
setSearchQuery(query);
18+
};
19+
20+
const handleSearchQueryChange = (query: string) => {
21+
setSearchQuery(query);
1722
};
1823

1924
return (
20-
<Layout onSearch={handleSearch}>
25+
<Layout onSearch={handleSearch} searchQuery={searchQuery} onSearchQueryChange={handleSearchQueryChange}>
2126
{/* Hero Section */}
2227
<div className="bg-gradient-to-r from-primary/10 to-primary/20 rounded-lg p-8 mb-8 text-center">
2328
<h1 className="text-4xl md:text-5xl font-bold mb-4">Книги по Python</h1>
@@ -37,7 +42,7 @@ export default function HomePage() {
3742
</div>
3843

3944
{/* Books List */}
40-
<BooksList onBookClick={handleBookClick} />
45+
<BooksList onBookClick={handleBookClick} searchQuery={searchQuery} />
4146
</Layout>
4247
);
4348
}

frontend/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as path from 'path'
66
export default defineConfig({
77
plugins: [react()],
88
server: {
9-
port: 8006,
9+
port: 5173,
1010
strictPort: true,
1111
},
1212
resolve: {

0 commit comments

Comments
 (0)