搜索
在 RESTful API 中实现搜索功能,你需要先定义一个处理搜索参数的路由,然后在底层数据库中使用前缀或全文索引进行搜索,再返回搜索结果。
在 MySQL 中搜索
添加 keyword
参数到 BookManager.GetBooks
,domain/gateway/book_manager.go:
@@ -12,5 +12,5 @@ type BookManager interface {
UpdateBook(ctx context.Context, id uint, b *model.Book) error
DeleteBook(ctx context.Context, id uint) error
GetBook(ctx context.Context, id uint) (*model.Book, error)
- GetBooks(ctx context.Context, offset int) ([]*model.Book, error)
+ GetBooks(ctx context.Context, offset int, keyword string) ([]*model.Book, error)
}
添加搜索功能,infrastructure/database/mysql.go:
@@ -55,9 +55,14 @@ func (s *MySQLPersistence) GetBook(ctx context.Context, id uint) (*model.Book, e
return &book, nil
}
-func (s *MySQLPersistence) GetBooks(ctx context.Context, offset int) ([]*model.Book, error) {
+func (s *MySQLPersistence) GetBooks(ctx context.Context, offset int, keyword string) ([]*model.Book, error) {
books := make([]*model.Book, 0)
- if err := s.db.WithContext(ctx).Offset(offset).Limit(s.pageSize).Find(&books).Error; err != nil {
+ tx := s.db.WithContext(ctx)
+ if keyword != "" {
+ term := "%" + keyword + "%"
+ tx = tx.Where("title LIKE ?", term).Or("author LIKE ?", term)
+ }
+ if err := tx.Offset(offset).Limit(s.pageSize).Find(&books).Error; err != nil {
return nil, err
}
return books, nil
注意:
在生产数据库中不要使用
LIKE %keyword%
。与其他搜索方法相比,这种方法效率较低,特别是在处理大型数据集时。LIKE %keyword%
语法强制数据库执行全表扫描或索引扫描,这可能会很慢,特别是在大型表上。它不能有效地利用索引,导致查询性能较慢。
如果你的用例允许,考虑使用前缀搜索(例如,LIKE keyword%
)。与子字符串搜索相比,这可以更有效地利用索引。
调整 application/executor/book_operator.go:
@@ -34,7 +34,13 @@ func (o *BookOperator) GetBook(ctx context.Context, id uint) (*model.Book, error
return o.bookManager.GetBook(ctx, id)
}
-func (o *BookOperator) GetBooks(ctx context.Context, offset int) ([]*model.Book, error) {
+func (o *BookOperator) GetBooks(ctx context.Context, offset int, query string) ([]*model.Book, error) {
+ // 搜索结果,不缓存
+ if query != "" {
+ return o.bookManager.GetBooks(ctx, offset, query)
+ }
+
+ // 普通结果列表
k := fmt.Sprintf("%s-%d", booksKey, offset)
rawValue, err := o.cacheHelper.Load(ctx, k)
if err != nil {
@@ -49,7 +55,7 @@ func (o *BookOperator) GetBooks(ctx context.Context, offset int) ([]*model.Book,
}
} else {
// Cache key does not exist
- books, err = o.bookManager.GetBooks(ctx, offset)
+ books, err = o.bookManager.GetBooks(ctx, offset, "")
if err != nil {
return nil, err
}
传入 query
参数,adaptor/router.go:
@@ -15,6 +15,7 @@ import (
const (
fieldID = "id"
fieldOffset = "o"
+ fieldQuery = "q"
)
// RestHandler handles all restful requests
@@ -63,7 +64,7 @@ func (r *RestHandler) getBooks(c *gin.Context) {
}
offset = value
}
- books, err := r.bookOperator.GetBooks(c, offset)
+ books, err := r.bookOperator.GetBooks(c, offset, c.Query(fieldQuery))
if err != nil {
fmt.Printf("Failed to get books: %v\n", err)
c.JSON(http.StatusNotFound, gin.H{"error": "failed to get books"})
保存修改,重启 api 服务器。
使用 curl 搜索图书
搜索图书
curl -X GET http://localhost:8080/books?q=and
结果:
[
{
"id": 5,
"title": "Pride and Prejudice",
"author": "Jane Austen",
"published_at": "1813-01-28",
"description": "A classic novel exploring the themes of love, reputation, and social class in Georgian England.",
"isbn": "9780486284736",
"total_pages": 279,
"created_at": "2024-02-26T17:28:54.213+08:00",
"updated_at": "2024-02-26T17:28:54.213+08:00"
},
{
"id": 11,
"title": "War and Peace",
"author": "Leo Tolstoy",
"published_at": "1869-01-01",
"description": "A novel depicting the Napoleonic era in Russia, exploring themes of love, war, and historical determinism.",
"isbn": "9781400079988",
"total_pages": 1392,
"created_at": "2024-02-26T17:28:54.309+08:00",
"updated_at": "2024-02-26T17:28:54.309+08:00"
},
{
"id": 13,
"title": "Alice’s Adventures in Wonderland",
"author": "Lewis Carroll",
"published_at": "1865-11-26",
"description": "A children’s novel featuring a young girl named Alice who falls into a fantastical world populated by peculiar creatures.",
"isbn": "9780141439761",
"total_pages": 192,
"created_at": "2024-02-26T17:31:55.903+08:00",
"updated_at": "2024-02-26T17:31:55.903+08:00"
}
]
搜索图书并带一个偏移
curl -X GET http://localhost:8080/books?q=the&o=4
结果:
[
{
"id": 10,
"title": "The Adventures of Huckleberry Finn",
"author": "Mark Twain",
"published_at": "1884-12-10",
"description": "A novel depicting the journey of a young boy and an escaped slave along the Mississippi River.",
"isbn": "9780486280615",
"total_pages": 366,
"created_at": "2024-02-26T17:28:54.293+08:00",
"updated_at": "2024-02-26T17:28:54.293+08:00"
},
{
"id": 12,
"title": "The Odyssey",
"author": "Homer",
"published_at": "8th Century BC",
"description": "An ancient Greek epic poem attributed to Homer, detailing the journey of Odysseus after the Trojan War.",
"isbn": "9780140268867",
"total_pages": 541,
"created_at": "2024-02-26T17:29:22.386+08:00",
"updated_at": "2024-02-26T17:29:22.386+08:00"
}
]
在 mongoDB 中搜索
添加 keyword
参数到 ReviewManager.GetReviewsOfBook
,domain/gateway/review_manager.go:
@@ -12,5 +12,5 @@ type ReviewManager interface {
UpdateReview(ctx context.Context, id string, b *model.Review) error
DeleteReview(ctx context.Context, id string) error
GetReview(ctx context.Context, id string) (*model.Review, error)
- GetReviewsOfBook(ctx context.Context, bookID uint) ([]*model.Review, error)
+ GetReviewsOfBook(ctx context.Context, bookID uint, keyword string) ([]*model.Review, error)
}
添加搜索功能,infrastructure/database/mongo.go:
@@ -96,8 +96,20 @@ func (m *MongoPersistence) GetReview(ctx context.Context, id string) (*model.Rev
return &review, nil
}
-func (m *MongoPersistence) GetReviewsOfBook(ctx context.Context, bookID uint) ([]*model.Review, error) {
- cursor, err := m.coll.Find(ctx, bson.M{bookIDField: bookID})
+func (m *MongoPersistence) GetReviewsOfBook(ctx context.Context, bookID uint, keyword string) ([]*model.Review, error) {
+ filter := bson.M{bookIDField: bookID}
+ if keyword != "" {
+ filter = bson.M{
+ "$and": []bson.M{
+ {"$or": []bson.M{
+ {"title": bson.M{"$regex": keyword, "$options": "i"}},
+ {"content": bson.M{"$regex": keyword, "$options": "i"}},
+ }},
+ {bookIDField: bookID},
+ },
+ }
+ }
+ cursor, err := m.coll.Find(ctx, filter)
if err != nil {
return nil, err
}
注意:
正则表达式查询无法充分利用索引。虽然某些操作可能仍然从索引中受益,但与精确匹配或前缀搜索相比,使用正则表达式可能效率较低。
如果你的集合包含大量文档,并且被搜索的字段没有建立索引,可能会导致查询性能较慢。
微调 application/executor/review_operator.go:
@@ -40,8 +40,8 @@ func (o *ReviewOperator) GetReview(ctx context.Context, id string) (*model.Revie
return o.reviewManager.GetReview(ctx, id)
}
-func (o *ReviewOperator) GetReviewsOfBook(ctx context.Context, bookID uint) ([]*model.Review, error) {
- return o.reviewManager.GetReviewsOfBook(ctx, bookID)
+func (o *ReviewOperator) GetReviewsOfBook(ctx context.Context, bookID uint, query string) ([]*model.Review, error) {
+ return o.reviewManager.GetReviewsOfBook(ctx, bookID, query)
}
func (o *ReviewOperator) UpdateReview(ctx context.Context, id string, b *model.Review) (*model.Review, error) {
传入 query
参数,adaptor/router.go:
@@ -152,7 +152,7 @@ func (r *RestHandler) getReviewsOfBook(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid book id"})
return
}
- books, err := r.reviewOperator.GetReviewsOfBook(c, uint(bookID))
+ books, err := r.reviewOperator.GetReviewsOfBook(c, uint(bookID), c.Query(fieldQuery))
if err != nil {
fmt.Printf("Failed to get reviews of book %d: %v\n", bookID, err)
c.JSON(http.StatusNotFound, gin.H{"error": "failed to get books"})
利用 mongoDB 实现搜索功能所需的更改已经全部加入。让我们测试一波。
使用 curl 尝试搜索书评
先加入一些假书评数据:
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Alice Johnson", "title": "A Timeless Classic", "content": "The Great Gatsby is a timeless classic that delves deep into the complexities of the human psyche and the pursuit of the American Dream."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Michael Adams", "title": "Brilliantly Written", "content": "Fitzgerald’s prose in The Great Gatsby is simply brilliant. Each sentence is crafted with care, drawing the reader into a world of opulence and tragedy."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Emily Parker", "title": "Mesmerizing", "content": "I was completely mesmerized by The Great Gatsby. Fitzgerald’s ability to create such vivid characters and evoke a sense of longing is unmatched."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Daniel White", "title": "Enthralling Plot", "content": "The plot of The Great Gatsby is enthralling from start to finish. It’s a story of love, loss, and the emptiness of the American Dream."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Sophia Lee", "title": "A Literary Gem", "content": "The Great Gatsby is a literary gem that shines with its insightful commentary on society and human nature. A must-read for all."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Ethan Miller", "title": "Timeless Masterpiece", "content": "The Great Gatsby remains a timeless masterpiece that continues to resonate with readers across generations. Fitzgerald’s prose is as relevant today as it was in the 1920s."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Olivia Wilson", "title": "Immersive Experience", "content": "Reading The Great Gatsby is an immersive experience like no other. Fitzgerald’s vivid descriptions transport you to the roaring twenties, making you feel like you’re part of the story."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Jacob Thompson", "title": "Intriguing Characters", "content": "What sets The Great Gatsby apart are its intriguing characters. Each one is flawed yet fascinating, contributing to the richness of the narrative."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Ava Martinez", "title": "Gripping Narrative", "content": "The Great Gatsby grips you from the first page and doesn’t let go until the very end. It’s a story that lingers in your mind long after you’ve finished reading."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Noah Taylor", "title": "Profound Themes", "content": "Beneath its glitzy surface, The Great Gatsby explores profound themes of love, betrayal, and the corrupting influence of wealth. A true masterpiece."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Isabella Hernandez", "title": "Hauntingly Beautiful", "content": "The Great Gatsby is hauntingly beautiful, painting a picture of an era filled with glamour and excess, yet tinged with sadness and longing."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Lucas Moore", "title": "Compelling Narrative", "content": "Fitzgerald weaves a compelling narrative in The Great Gatsby, drawing readers into the world of Jay Gatsby and Daisy Buchanan with finesse and skill."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Mia Clark", "title": "Unforgettable Characters", "content": "The characters in The Great Gatsby are unforgettable, each with their own desires and flaws that drive the story forward with intensity and emotion."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Elijah Garcia", "title": "Eloquent Prose", "content": "Fitzgerald’s eloquent prose in The Great Gatsby elevates the novel to literary greatness. It’s a book that demands to be savored and appreciated."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Charlotte King", "title": "Riveting Plot", "content": "The plot of The Great Gatsby is riveting, filled with twists and turns that keep you on the edge of your seat until the very end. An absolute page-turner."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "William Brown", "title": "Emotionally Resonant", "content": "The Great Gatsby is emotionally resonant, exploring themes of love and longing in a way that stays with you long after you’ve turned the final page."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Chloe Rodriguez", "title": "Sensory Delight", "content": "Reading The Great Gatsby is a sensory delight, with Fitzgerald’s vivid descriptions bringing the sights, sounds, and smells of the 1920s to life."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "James Lee", "title": "Thought-Provoking", "content": "The Great Gatsby is thought-provoking, challenging readers to reflect on the nature of wealth, ambition, and the pursuit of happiness."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Emma Taylor", "title": "Rich Symbolism", "content": "The Great Gatsby is rich in symbolism, with every detail serving a purpose in conveying deeper themes and messages about society and human nature."}' http://localhost:8080/reviews
curl -X POST -H "Content-Type: application/json" -d '{"book_id": 2, "author": "Ryan Martinez", "title": "A Literary Masterpiece", "content": "The Great Gatsby is undeniably a literary masterpiece, with its lyrical prose and timeless themes making it a must-read for all lovers of literature."}' http://localhost:8080/reviews
根据 title 和 content 搜索书评,关键字:masterpiece
curl -X GET "http://localhost:8080/books/2/reviews?q=masterpiece"
结果:
[
{
"id": "65dc91f5607f19bc5103ac51",
"book_id": 2,
"author": "Ethan Miller",
"title": "Timeless Masterpiece",
"content": "The Great Gatsby remains a timeless masterpiece that continues to resonate with readers across generations. Fitzgerald’s prose is as relevant today as it was in the 1920s.",
"created_at": "2024-02-26T13:28:21.088Z",
"updated_at": "2024-02-26T13:28:21.088Z"
},
{
"id": "65dc91f5607f19bc5103ac55",
"book_id": 2,
"author": "Noah Taylor",
"title": "Profound Themes",
"content": "Beneath its glitzy surface, The Great Gatsby explores profound themes of love, betrayal, and the corrupting influence of wealth. A true masterpiece.",
"created_at": "2024-02-26T13:28:21.145Z",
"updated_at": "2024-02-26T13:28:21.145Z"
},
{
"id": "65dc91f5607f19bc5103ac5f",
"book_id": 2,
"author": "Ryan Martinez",
"title": "A Literary Masterpiece",
"content": "The Great Gatsby is undeniably a literary masterpiece, with its lyrical prose and timeless themes making it a must-read for all lovers of literature.",
"created_at": "2024-02-26T13:28:21.287Z",
"updated_at": "2024-02-26T13:28:21.287Z"
}
]
根据 title 和 content 搜索书评,关键字:Fitzgerald
curl -X GET "http://localhost:8080/books/2/reviews?q=Fitzgerald"
结果:
[
{
"id": "65dc91f5607f19bc5103ac4d",
"book_id": 2,
"author": "Michael Adams",
"title": "Brilliantly Written",
"content": "Fitzgerald’s prose in The Great Gatsby is simply brilliant. Each sentence is crafted with care, drawing the reader into a world of opulence and tragedy.",
"created_at": "2024-02-26T13:28:21.029Z",
"updated_at": "2024-02-26T13:28:21.029Z"
},
{
"id": "65dc91f5607f19bc5103ac4e",
"book_id": 2,
"author": "Emily Parker",
"title": "Mesmerizing",
"content": "I was completely mesmerized by The Great Gatsby. Fitzgerald’s ability to create such vivid characters and evoke a sense of longing is unmatched.",
"created_at": "2024-02-26T13:28:21.043Z",
"updated_at": "2024-02-26T13:28:21.043Z"
},
{
"id": "65dc91f5607f19bc5103ac51",
"book_id": 2,
"author": "Ethan Miller",
"title": "Timeless Masterpiece",
"content": "The Great Gatsby remains a timeless masterpiece that continues to resonate with readers across generations. Fitzgerald’s prose is as relevant today as it was in the 1920s.",
"created_at": "2024-02-26T13:28:21.088Z",
"updated_at": "2024-02-26T13:28:21.088Z"
},
{
"id": "65dc91f5607f19bc5103ac52",
"book_id": 2,
"author": "Olivia Wilson",
"title": "Immersive Experience",
"content": "Reading The Great Gatsby is an immersive experience like no other. Fitzgerald’s vivid descriptions transport you to the roaring twenties, making you feel like you’re part of the story.",
"created_at": "2024-02-26T13:28:21.102Z",
"updated_at": "2024-02-26T13:28:21.102Z"
},
{
"id": "65dc91f5607f19bc5103ac57",
"book_id": 2,
"author": "Lucas Moore",
"title": "Compelling Narrative",
"content": "Fitzgerald weaves a compelling narrative in The Great Gatsby, drawing readers into the world of Jay Gatsby and Daisy Buchanan with finesse and skill.",
"created_at": "2024-02-26T13:28:21.173Z",
"updated_at": "2024-02-26T13:28:21.173Z"
},
{
"id": "65dc91f5607f19bc5103ac59",
"book_id": 2,
"author": "Elijah Garcia",
"title": "Eloquent Prose",
"content": "Fitzgerald’s eloquent prose in The Great Gatsby elevates the novel to literary greatness. It’s a book that demands to be savored and appreciated.",
"created_at": "2024-02-26T13:28:21.201Z",
"updated_at": "2024-02-26T13:28:21.201Z"
},
{
"id": "65dc91f5607f19bc5103ac5c",
"book_id": 2,
"author": "Chloe Rodriguez",
"title": "Sensory Delight",
"content": "Reading The Great Gatsby is a sensory delight, with Fitzgerald’s vivid descriptions bringing the sights, sounds, and smells of the 1920s to life.",
"created_at": "2024-02-26T13:28:21.244Z",
"updated_at": "2024-02-26T13:28:21.244Z"
}
]
不错!基于 MySQL 和 mongoDB 的搜索功能已完成!
高级全文搜索
如果你想要拥有高级全文搜索支持,请尝试 Elasticsearch 或 Solr。 这些解决方案针对文本搜索操作进行了优化,并提供诸如索引、相关性评分和语言特定的词干处理等功能。