自定义排名 #
排名机制回顾 #
默认排名公式 #
text
排名 = typo → geo → words → filters → proximity → attribute → exact → custom
排名顺序 #
排名按顺序比较,前面的维度优先级更高:
text
记录A: typo=0, words=2, custom=100
记录B: typo=0, words=1, custom=200
结果: A排在B前面(因为words维度A更高)
自定义排名配置 #
基本设置 #
javascript
await index.setSettings({
customRanking: [
'desc(rating)', // 评分降序
'desc(popularity)', // 人气降序
'asc(price)' // 价格升序
]
});
排名方向 #
| 方向 | 说明 | 使用场景 |
|---|---|---|
| desc | 降序 | 评分、人气、销量 |
| asc | 升序 | 价格、距离 |
业务排名策略 #
电商场景 #
javascript
await index.setSettings({
customRanking: [
'desc(qualityScore)', // 质量分
'desc(salesCount)', // 销量
'desc(rating)', // 评分
'asc(price)' // 价格
]
});
内容场景 #
javascript
await index.setSettings({
customRanking: [
'desc(freshness)', // 新鲜度
'desc(engagement)', // 参与度
'desc(viewCount)' // 浏览量
]
});
用户场景 #
javascript
await index.setSettings({
customRanking: [
'desc(lastActiveAt)', // 最近活跃
'desc(followers)', // 粉丝数
'desc(posts)' // 发帖数
]
});
质量分数计算 #
综合质量分 #
javascript
// 数据准备时计算质量分数
function calculateQualityScore(product) {
const ratingScore = product.rating * 20; // 0-100
const salesScore = Math.min(product.salesCount / 100, 100);
const reviewScore = Math.min(product.reviewCount / 10, 100);
const stockScore = product.inStock ? 100 : 0;
return {
...product,
qualityScore: (ratingScore + salesScore + reviewScore + stockScore) / 4
};
}
// 索引数据
const productsWithScore = products.map(calculateQualityScore);
await index.saveObjects(productsWithScore);
新鲜度分数 #
javascript
function calculateFreshness(publishedAt) {
const now = Date.now();
const age = now - publishedAt;
const dayAge = age / (1000 * 60 * 60 * 24);
// 指数衰减
const halfLife = 7; // 7天半衰期
return 100 * Math.exp(-0.693 * dayAge / halfLife);
}
// 数据
{
"publishedAt": 1710432000,
"freshness": 85.5
}
参与度分数 #
javascript
function calculateEngagement(content) {
const viewWeight = 0.3;
const likeWeight = 0.4;
const commentWeight = 0.3;
const viewScore = Math.min(content.viewCount / 1000, 100);
const likeScore = Math.min(content.likeCount / 100, 100);
const commentScore = Math.min(content.commentCount / 50, 100);
return viewScore * viewWeight +
likeScore * likeWeight +
commentScore * commentWeight;
}
排名规则 #
创建排名规则 #
javascript
await index.saveRule({
objectID: 'promo-rule',
condition: {
pattern: 'sale',
anchoring: 'contains'
},
consequence: {
params: {
filters: 'onSale:true',
optionalFilters: ['brand:Apple<score=2>']
}
}
});
规则示例 #
javascript
// 促销规则
{
objectID: 'promo-apple',
condition: { pattern: 'apple', anchoring: 'contains' },
consequence: {
params: {
optionalFilters: ['brand:Apple<score=5>']
}
}
}
// 新品规则
{
objectID: 'new-arrivals',
condition: { pattern: 'new', anchoring: 'contains' },
consequence: {
params: {
filters: 'isNew:true',
optionalFilters: ['createdAt:>1710000000<score=3>']
}
}
}
可选过滤器 #
基本用法 #
javascript
const results = await index.search('phone', {
optionalFilters: ['brand:Apple<score=2>']
});
// Apple品牌的结果排名更高,但不排除其他品牌
评分权重 #
javascript
// 更高的score值意味着更高的排名提升
optionalFilters: [
'brand:Apple<score=5>',
'brand:Samsung<score=3>',
'brand:Google<score=1>'
]
组合使用 #
javascript
const results = await index.search('laptop', {
filters: 'inStock:true',
optionalFilters: [
'brand:Apple<score=3>',
'rating:>4.5<score=2>',
'price:<1000<score=1>'
]
});
动态排名 #
基于时间的排名 #
javascript
// 数据中包含时间戳
{
"name": "Product",
"createdAt": 1710432000,
"boostUntil": 1712505600 // 提升截止时间
}
// 搜索时检查
function searchWithTimeBoost(query) {
const now = Math.floor(Date.now() / 1000);
return index.search(query, {
optionalFilters: [`boostUntil:>${now}<score=5>`]
});
}
基于用户行为 #
javascript
// 个性化排名
async function personalizedSearch(query, userId) {
const userPreferences = await getUserPreferences(userId);
const optionalFilters = userPreferences.brands.map(brand =>
`brand:${brand}<score=3>`
);
return index.search(query, {
optionalFilters,
enablePersonalization: true,
userToken: userId
});
}
排名调试 #
获取排名信息 #
javascript
const results = await index.search('iphone', {
getRankingInfo: true
});
results.hits.forEach(hit => {
console.log(hit.name, hit._rankingInfo);
});
排名信息字段 #
javascript
{
"_rankingInfo": {
"nbTypos": 0,
"firstMatchedWord": 0,
"proximityDistance": 1,
"userScore": 100,
"geoDistance": 0,
"geoPrecision": 1,
"nbExactWords": 1,
"words": 1,
"filters": 1
}
}
排名分析工具 #
javascript
class RankingAnalyzer {
constructor(index) {
this.index = index;
}
async analyze(query) {
const results = await this.index.search(query, {
getRankingInfo: true,
hitsPerPage: 20
});
return results.hits.map((hit, index) => ({
position: index + 1,
name: hit.name,
score: hit._rankingInfo.userScore,
details: hit._rankingInfo
}));
}
compare(query, expectedOrder) {
const results = await this.analyze(query);
const actualOrder = results.map(r => r.name);
return {
expected: expectedOrder,
actual: actualOrder,
match: JSON.stringify(expectedOrder) === JSON.stringify(actualOrder)
};
}
}
排名优化案例 #
案例1:电商促销 #
javascript
// 需求:促销商品优先展示
// 方案:使用可选过滤器
async function searchWithPromo(query) {
return index.search(query, {
optionalFilters: [
'onSale:true<score=10>',
'discount:>20<score=5>'
]
});
}
案例2:新品优先 #
javascript
// 需求:新品排在前面
// 方案:预计算新鲜度分数
// 数据准备
function prepareProduct(product) {
const now = Date.now();
const age = now - product.createdAt;
const dayAge = age / (1000 * 60 * 60 * 24);
return {
...product,
freshness: Math.max(0, 100 - dayAge)
};
}
// 排名设置
customRanking: ['desc(freshness)', 'desc(rating)']
案例3:个性化推荐 #
javascript
// 需求:根据用户偏好排名
// 方案:使用个性化API
async function personalizedSearch(query, userId) {
return index.search(query, {
enablePersonalization: true,
userToken: userId,
personalizationImpact: 50
});
}
排名最佳实践 #
1. 预计算复杂分数 #
javascript
// ✅ 推荐:预先计算
{
"qualityScore": 85,
"freshness": 90
}
// ❌ 避免:运行时计算
// customRanking: ['desc(rating * salesCount)'] // 不支持
2. 合理设置排名顺序 #
javascript
// ✅ 推荐:按业务重要性排序
customRanking: [
'desc(qualityScore)', // 最重要
'desc(popularity)', // 次重要
'asc(price)' // 最后考虑
]
3. 使用可选过滤器 #
javascript
// ✅ 推荐:使用可选过滤器提升特定结果
optionalFilters: ['brand:Apple<score=5>']
// ❌ 避免:使用过滤器排除结果
filters: 'brand:Apple' // 会排除其他品牌
4. 定期优化 #
javascript
// 分析搜索数据,优化排名
async function optimizeRanking() {
const analytics = await getSearchAnalytics();
// 找出点击率低的搜索词
const lowCTR = analytics.filter(a => a.ctr < 0.1);
// 分析原因,调整排名
// ...
}
总结 #
自定义排名要点:
| 要点 | 说明 |
|---|---|
| 配置 | customRanking设置 |
| 方向 | desc降序,asc升序 |
| 质量分 | 预计算综合分数 |
| 规则 | 动态调整排名 |
| 可选过滤 | 提升特定结果 |
| 调试 | getRankingInfo参数 |
接下来,让我们学习 搜索建议。
最后更新:2026-03-28