1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
import { Client } from '@elastic/elasticsearch';
const esClient = new Client({
node: 'http://localhost:9200',
auth: {
username: 'elastic',
password: '...',
}
});
async function ensureIndexExist() {
const indexName = 'documents';
const exist = await esClient.indices.exists({ index: indexName });
if (!exist) {
await esClient.indices.create({
index: indexName,
body: {
mappings: {
properties: {
title: { type: 'text' },
content: { type: 'text' },
createAt: { type: 'date' },
}
}
}
});
}
}
// 初始化索引
await ensureIndexExist().catch(console.error);
app.post('/doc', async (req, res) => {
try {
const { title, content } = req.body;
if (!title || !content) {
return res.status(400).json({ error: "title and content required" });
}
const doc = {
title,
content,
createAt: new Date().toISOString()
};
const result = await esClient.index({
index: 'documents',
document: doc,
refresh: true
});
res.status(201).json({
status: 'accept',
id: result._id
});
} catch (error) {
console.error('Indexing error:', error);
res.status(500).json({ status: 'reject' });
}
});
app.get('/search', async (req, res) => {
try {
const { q } = req.query;
if (!q) {
return res.status(400).json({ error: 'Query parameter "q" is required' });
}
const result = await esClient.search({
index: 'documents',
body: {
query: {
multi_match: {
query: q,
fields: ['title', 'content']
}
}
}
});
const hits = result.hits.hits.map(hit => ({
id: hit._id,
...hit._source
}));
res.json({
total: result.hits.total.value,
results: hits
});
} catch (error) {
console.error('Search error:', error);
res.status(500).json({ status: 'reject' });
}
});
|