// SearchEngine Frontend JavaScript
// API endpoint
const API_BASE_URL = 'http://120.76.41.98:6002';
// Update API URL display
document.getElementById('apiUrl').textContent = API_BASE_URL;
// Handle Enter key in search input
function handleKeyPress(event) {
if (event.key === 'Enter') {
performSearch();
}
}
// Set query from example buttons
function setQuery(query) {
document.getElementById('searchInput').value = query;
performSearch();
}
// 全局变量存储当前的过滤条件
let currentFilters = {};
// Perform search
async function performSearch() {
const query = document.getElementById('searchInput').value.trim();
if (!query) {
alert('请输入搜索关键词');
return;
}
// Get options
const size = parseInt(document.getElementById('resultSize').value);
const sortByValue = document.getElementById('sortBy').value;
// Parse sort option
let sort_by = null;
let sort_order = 'desc';
if (sortByValue) {
const [field, order] = sortByValue.split(':');
sort_by = field;
sort_order = order;
}
// Define aggregations for faceted search
const aggregations = {
"category_stats": {
"terms": {
"field": "categoryName_keyword",
"size": 10
}
},
"brand_stats": {
"terms": {
"field": "brandName_keyword",
"size": 10
}
},
"supplier_stats": {
"terms": {
"field": "supplierName_keyword",
"size": 10
}
},
"price_ranges": {
"range": {
"field": "price",
"ranges": [
{"key": "0-50", "to": 50},
{"key": "50-100", "from": 50, "to": 100},
{"key": "100-200", "from": 100, "to": 200},
{"key": "200+", "from": 200}
]
}
}
};
// Show loading
document.getElementById('loading').style.display = 'block';
document.getElementById('results').innerHTML = '';
document.getElementById('queryInfo').innerHTML = '';
document.getElementById('aggregationResults').innerHTML = '';
try {
const response = await fetch(`${API_BASE_URL}/search/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: query,
size: size,
filters: Object.keys(currentFilters).length > 0 ? currentFilters : null,
aggregations: aggregations,
sort_by: sort_by,
sort_order: sort_order
})
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
displayResults(data);
displayQueryInfo(data.query_info);
displayAggregations(data.aggregations);
displayActiveFilters();
} catch (error) {
console.error('Search error:', error);
document.getElementById('results').innerHTML = `
搜索出错: ${error.message}
请确保后端服务正在运行 (${API_BASE_URL})
`;
} finally {
document.getElementById('loading').style.display = 'none';
}
}
// Display search results
function displayResults(data) {
const resultsDiv = document.getElementById('results');
if (!data.hits || data.hits.length === 0) {
resultsDiv.innerHTML = `
`;
return;
}
let html = `
`;
data.hits.forEach((hit, index) => {
const source = hit._source;
const score = hit._custom_score || hit._score;
html += `
${source.price ? `💰 ¥${escapeHtml(source.price)} ` : ''}
${source.categoryName ? `📁 ${escapeHtml(source.categoryName)} ` : ''}
${source.brandName ? `🏷️ ${escapeHtml(source.brandName)} ` : ''}
${source.supplierName ? `🏭 ${escapeHtml(source.supplierName)} ` : ''}
${source.create_time ? `📅 ${formatDate(source.create_time)} ` : ''}
${source.imageUrl ? `
` : ''}
ID: ${source.skuId || 'N/A'}
`;
});
resultsDiv.innerHTML = html;
}
// Display query processing information
function displayQueryInfo(queryInfo) {
if (!queryInfo) return;
const queryInfoDiv = document.getElementById('queryInfo');
let html = `
查询处理信息
原始查询
${escapeHtml(queryInfo.original_query || 'N/A')}
重写后查询
${escapeHtml(queryInfo.rewritten_query || 'N/A')}
检测语言
${getLanguageName(queryInfo.detected_language)}
查询域
${escapeHtml(queryInfo.domain || 'default')}
`;
// Show translations if any
if (queryInfo.translations && Object.keys(queryInfo.translations).length > 0) {
html += '翻译结果 ';
for (const [lang, translation] of Object.entries(queryInfo.translations)) {
if (translation) {
html += `
${getLanguageName(lang)}
${escapeHtml(translation)}
`;
}
}
html += '
';
}
// Show embedding info
if (queryInfo.has_vector) {
html += `
✓ 使用了语义向量搜索
`;
}
queryInfoDiv.innerHTML = html;
}
// Helper functions
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
function formatDate(dateStr) {
try {
const date = new Date(dateStr);
return date.toLocaleDateString('zh-CN');
} catch {
return dateStr;
}
}
function getLanguageName(code) {
const names = {
'zh': '中文',
'en': 'English',
'ru': 'Русский',
'ar': 'العربية',
'ja': '日本語',
'unknown': '未知'
};
return names[code] || code;
}
// Display aggregations
function displayAggregations(aggregations) {
if (!aggregations || Object.keys(aggregations).length === 0) {
document.getElementById('aggregationPanel').style.display = 'none';
return;
}
document.getElementById('aggregationPanel').style.display = 'block';
const aggregationResultsDiv = document.getElementById('aggregationResults');
let html = '';
// Category aggregation
if (aggregations.category_stats && aggregations.category_stats.buckets) {
html += `
';
}
// Brand aggregation
if (aggregations.brand_stats && aggregations.brand_stats.buckets) {
html += `
';
}
// Supplier aggregation
if (aggregations.supplier_stats && aggregations.supplier_stats.buckets) {
html += `
';
}
// Price range aggregation
if (aggregations.price_ranges && aggregations.price_ranges.buckets) {
html += `
';
}
aggregationResultsDiv.innerHTML = html;
}
// Display active filters
function displayActiveFilters() {
const activeFiltersDiv = document.getElementById('activeFilters');
if (Object.keys(currentFilters).length === 0) {
activeFiltersDiv.innerHTML = '';
return;
}
let html = '';
Object.entries(currentFilters).forEach(([field, values]) => {
if (Array.isArray(values)) {
values.forEach(value => {
let displayValue = value;
if (field === 'price_ranges') {
const priceLabel = {
'0-50': '¥0-50',
'50-100': '¥50-100',
'100-200': '¥100-200',
'200+': '¥200+'
};
displayValue = priceLabel[value] || value;
}
html += `
${escapeHtml(displayValue)}
×
`;
});
}
});
html += `清除所有
`;
activeFiltersDiv.innerHTML = html;
}
// Toggle filter
function toggleFilter(field, value, checked) {
if (checked) {
if (!currentFilters[field]) {
currentFilters[field] = [];
}
if (!currentFilters[field].includes(value)) {
currentFilters[field].push(value);
}
} else {
if (currentFilters[field]) {
const index = currentFilters[field].indexOf(value);
if (index > -1) {
currentFilters[field].splice(index, 1);
}
if (currentFilters[field].length === 0) {
delete currentFilters[field];
}
}
}
// Re-run search with new filters
performSearch();
}
// Toggle price filter
function togglePriceFilter(value, checked) {
if (checked) {
if (!currentFilters.price_ranges) {
currentFilters.price_ranges = [];
}
if (!currentFilters.price_ranges.includes(value)) {
currentFilters.price_ranges.push(value);
}
} else {
if (currentFilters.price_ranges) {
const index = currentFilters.price_ranges.indexOf(value);
if (index > -1) {
currentFilters.price_ranges.splice(index, 1);
}
if (currentFilters.price_ranges.length === 0) {
delete currentFilters.price_ranges;
}
}
}
// Re-run search with new filters
performSearch();
}
// Remove single filter
function removeFilter(field, value) {
toggleFilter(field, value, false);
}
// Clear all filters
function clearAllFilters() {
currentFilters = {};
performSearch();
}
// Initialize page
document.addEventListener('DOMContentLoaded', function() {
console.log('SearchEngine Frontend loaded');
console.log('API Base URL:', API_BASE_URL);
// Focus on search input
document.getElementById('searchInput').focus();
});