发送 Search 请求
更新 src/domain/gateway/book_manager.ts:
@@ -2,4 +2,5 @@ import { Book } from "../model";
export interface BookManager {
indexBook(b: Book): Promise<string>;
+ searchBooks(q: string): Promise<Book[]>;
}
更新 src/infrastructure/search/es.ts:
@@ -21,4 +21,17 @@ export class ElasticSearchEngine implements BookManager {
});
return result._id;
}
+
+ async searchBooks(q: string): Promise<Book[]> {
+ const result = await this.client.search({
+ index: INDEX_BOOK,
+ query: {
+ multi_match: {
+ query: q,
+ fields: ["title", "author", "content"],
+ },
+ },
+ });
+ return result.hits.hits.map((hit) => hit._source as Book);
+ }
}
此处我们使用 multi_match
来进行多字段查询:“title”,“author”和“content”。
更新 src/application/executor/book_operator.ts:
@@ -11,4 +11,8 @@ export class BookOperator {
async createBook(b: Book): Promise<string> {
return await this.bookManager.indexBook(b);
}
+
+ async searchBooks(q: string): Promise<Book[]> {
+ return await this.bookManager.searchBooks(q);
+ }
}
更新 src/adapter/router.ts:
@@ -21,6 +21,18 @@ class RestHandler {
res.status(404).json({ error: "Failed to create" });
}
}
+
+ public async searchBooks(req: Request, res: Response): Promise<void> {
+ try {
+ const books = await this.bookOperator.searchBooks(
+ (req.query.q as string) || ""
+ );
+ res.status(201).json(books);
+ } catch (err) {
+ console.error(`Failed to search books: ${err}`);
+ res.status(404).json({ error: "Failed to search" });
+ }
+ }
}
// Create router
@@ -34,6 +46,7 @@ function MakeRouter(wireHelper: WireHelper): express.Router {
res.json({ status: "ok" });
});
router.post("/books", restHandler.createBook.bind(restHandler));
+ router.get("/books", restHandler.searchBooks.bind(restHandler));
return router;
}
重启后再次使用 curl
测试:
curl 'http://localhost:3000/books?q=katniss+hunger'
样例响应:
[
{
"title": "The Hunger Games",
"author": "Suzanne Collins",
"published_at": "2008-09-14",
"content": "In a dystopian future, teenagers are forced to participate in a televised death match called the Hunger Games. Katniss Everdeen volunteers to take her sister‘s place and becomes a symbol of rebellion."
}
]
http://localhost:3000/books?q=new%20york%20circus%20girl
在 URL 编码中,
%20
和+
都可以表示空格,但是它们的使用场景稍有区别。
赞!你刚刚完成了一个全文检索。
注意:
全文检索需要语言分词器。默认的标准分词器对中、日、韩文等语言处理效果不理想。 可以使用语言特定的分词器以获取更佳效果。