过滤与筛选 #

过滤概述 #

Algolia提供多种过滤方式来精确控制搜索结果:

过滤方式 用途 特点
filters 通用过滤 灵活的布尔表达式
facetFilters 分面过滤 简单易用,支持OR
numericFilters 数值过滤 数值比较
tagFilters 标签过滤 简单标签匹配

filters参数 #

基本语法 #

javascript
// 等于
filters: 'brand:Apple'

// 不等于
filters: 'brand != Apple'

// 比较运算
filters: 'price < 1000'
filters: 'price <= 1000'
filters: 'price > 500'
filters: 'price >= 500'

布尔运算 #

javascript
// AND
filters: 'brand:Apple AND price < 1000'

// OR
filters: 'brand:Apple OR brand:Samsung'

// NOT
filters: 'NOT brand:Apple'

// 组合
filters: '(brand:Apple OR brand:Samsung) AND price < 1000'

字符串过滤 #

javascript
// 精确匹配
filters: 'name:"iPhone 15 Pro"'

// 前缀匹配(需要特殊处理)
filters: 'name:iPhone'

// 包含空格的值需要引号
filters: 'category:"Smart Phones"'

布尔过滤 #

javascript
// 布尔值
filters: 'inStock:true'
filters: 'featured:false'

数组过滤 #

javascript
// 数组字段匹配任意元素
filters: 'tags:phone'

// 多个标签
filters: 'tags:phone AND tags:5g'

嵌套属性过滤 #

javascript
// 使用点号访问嵌套属性
filters: 'specs.ram:8GB'
filters: 'author.name:John'

facetFilters参数 #

单个过滤 #

javascript
// 单个分面值
facetFilters: ['brand:Apple']

AND关系 #

javascript
// 多个条件(AND关系)
facetFilters: [
  'brand:Apple',
  'category:Phones',
  'inStock:true'
]

OR关系 #

javascript
// 同一分面多选(OR关系)
facetFilters: [
  ['brand:Apple', 'brand:Samsung', 'brand:Google']
]

组合使用 #

javascript
// 复杂组合
facetFilters: [
  ['brand:Apple', 'brand:Samsung'],  // Apple或Samsung
  'category:Phones',                  // 且是手机
  ['color:Black', 'color:White'],    // 且是黑色或白色
  'inStock:true'                      // 且有库存
]

numericFilters参数 #

基本用法 #

javascript
// 单个条件
numericFilters: ['price < 1000']

// 多个条件
numericFilters: [
  'price >= 500',
  'price <= 1000',
  'rating > 4'
]

比较运算符 #

运算符 说明
= 等于
!= 不等于
> 大于
>= 大于等于
< 小于
<= 小于等于

组合条件 #

javascript
numericFilters: [
  'price >= 500',
  'price <= 1000',
  'stock > 0',
  'rating >= 4'
]

tagFilters参数 #

基本用法 #

javascript
// 单个标签
tagFilters: ['phone']

// 多个标签(AND关系)
tagFilters: ['phone', '5g']

// OR关系
tagFilters: [['phone', 'tablet']]

与数据字段配合 #

javascript
// 记录结构
{
  "_tags": ["phone", "5g", "apple"]
}

// 或使用tags字段
{
  "tags": ["phone", "5g", "apple"]
}

过滤器对比 #

filters vs facetFilters #

javascript
// filters - 更灵活
filters: 'brand:Apple AND (price < 1000 OR rating > 4)'

// facetFilters - 更简单
facetFilters: ['brand:Apple']  // 只能做简单的AND/OR

选择建议 #

场景 推荐
简单分面筛选 facetFilters
复杂布尔逻辑 filters
数值范围 filters 或 numericFilters
标签匹配 tagFilters

高级过滤 #

可选过滤器 #

javascript
// optionalFilters - 不影响搜索结果,只影响排名
index.search('phone', {
  optionalFilters: ['brand:Apple<score=2>'],
  filters: 'inStock:true'
});

// Apple品牌的结果排名更高,但不排除其他品牌

过滤器评分 #

javascript
// 为过滤器设置评分权重
index.search('phone', {
  optionalFilters: [
    'brand:Apple<score=5>',
    'brand:Samsung<score=3>'
  ]
});

动态过滤 #

javascript
function buildFilters(conditions) {
  const parts = [];
  
  if (conditions.brand) {
    parts.push(`brand:${conditions.brand}`);
  }
  
  if (conditions.minPrice || conditions.maxPrice) {
    const priceFilters = [];
    if (conditions.minPrice) {
      priceFilters.push(`price >= ${conditions.minPrice}`);
    }
    if (conditions.maxPrice) {
      priceFilters.push(`price <= ${conditions.maxPrice}`);
    }
    parts.push(`(${priceFilters.join(' AND ')})`);
  }
  
  if (conditions.inStock) {
    parts.push('inStock:true');
  }
  
  return parts.join(' AND ');
}

// 使用
const filters = buildFilters({
  brand: 'Apple',
  minPrice: 500,
  maxPrice: 1000,
  inStock: true
});
// 结果: "brand:Apple AND (price >= 500 AND price <= 1000) AND inStock:true"

过滤器安全 #

用户输入转义 #

javascript
function escapeFilterValue(value) {
  // 转义特殊字符
  return value.replace(/([\\'"(){}[\]:])/g, '\\$1');
}

// 使用
const userInput = "O'Reilly";
const safeValue = escapeFilterValue(userInput);
filters: `brand:"${safeValue}"`

使用参数化查询 #

javascript
// 使用数组形式避免注入
const brand = "O'Reilly";
const filters = `brand:${JSON.stringify(brand)}`;

过滤器性能 #

过滤器优化 #

javascript
// ✅ 推荐:使用facetFilters
facetFilters: ['brand:Apple', 'category:Phones']

// ⚠️ 可行但较慢:使用filters
filters: 'brand:Apple AND category:Phones'

避免复杂嵌套 #

javascript
// ❌ 避免:过度嵌套
filters: '((brand:Apple OR brand:Samsung) AND (price < 1000 OR rating > 4)) OR (brand:Google AND price < 800)'

// ✅ 推荐:简化条件
filters: 'brand:Apple AND price < 1000'

过滤器示例 #

电商过滤 #

javascript
async function filterProducts(options) {
  const {
    query = '',
    brands = [],
    categories = [],
    minPrice,
    maxPrice,
    inStock,
    minRating,
    colors = [],
    sizes = []
  } = options;
  
  const filterParts = [];
  
  // 品牌过滤
  if (brands.length > 0) {
    filterParts.push(`(${brands.map(b => `brand:${b}`).join(' OR ')})`);
  }
  
  // 分类过滤
  if (categories.length > 0) {
    filterParts.push(`(${categories.map(c => `category:${c}`).join(' OR ')})`);
  }
  
  // 价格范围
  if (minPrice !== undefined || maxPrice !== undefined) {
    const priceParts = [];
    if (minPrice !== undefined) priceParts.push(`price >= ${minPrice}`);
    if (maxPrice !== undefined) priceParts.push(`price <= ${maxPrice}`);
    filterParts.push(`(${priceParts.join(' AND ')})`);
  }
  
  // 库存过滤
  if (inStock !== undefined) {
    filterParts.push(`inStock:${inStock}`);
  }
  
  // 评分过滤
  if (minRating !== undefined) {
    filterParts.push(`rating >= ${minRating}`);
  }
  
  // 颜色过滤
  if (colors.length > 0) {
    filterParts.push(`(${colors.map(c => `color:${c}`).join(' OR ')})`);
  }
  
  // 尺寸过滤
  if (sizes.length > 0) {
    filterParts.push(`(${sizes.map(s => `size:${s}`).join(' OR ')})`);
  }
  
  return await index.search(query, {
    filters: filterParts.join(' AND '),
    facets: ['brand', 'category', 'color', 'size']
  });
}

内容过滤 #

javascript
async function filterContent(options) {
  const {
    query = '',
    types = [],
    authors = [],
    tags = [],
    dateFrom,
    dateTo,
    status = 'published'
  } = options;
  
  const filterParts = [];
  
  // 状态过滤
  filterParts.push(`status:${status}`);
  
  // 类型过滤
  if (types.length > 0) {
    filterParts.push(`(${types.map(t => `type:${t}`).join(' OR ')})`);
  }
  
  // 作者过滤
  if (authors.length > 0) {
    filterParts.push(`(${authors.map(a => `author.id:${a}`).join(' OR ')})`);
  }
  
  // 标签过滤
  if (tags.length > 0) {
    filterParts.push(`(${tags.map(t => `tags:${t}`).join(' OR ')})`);
  }
  
  // 日期范围
  if (dateFrom || dateTo) {
    const dateParts = [];
    if (dateFrom) dateParts.push(`publishedAt >= ${dateFrom}`);
    if (dateTo) dateParts.push(`publishedAt <= ${dateTo}`);
    filterParts.push(`(${dateParts.join(' AND ')})`);
  }
  
  return await index.search(query, {
    filters: filterParts.join(' AND '),
    facets: ['type', 'author.name', 'tags']
  });
}

地理位置过滤 #

javascript
async function geoSearch(options) {
  const {
    query = '',
    lat,
    lng,
    radius = 10000,  // 10公里
    country,
    city
  } = options;
  
  const searchParams = {
    facets: ['country', 'city']
  };
  
  // 地理位置过滤
  if (lat && lng) {
    searchParams.aroundLatLng = `${lat},${lng}`;
    searchParams.aroundRadius = radius;
  }
  
  // 国家/城市过滤
  const filterParts = [];
  if (country) filterParts.push(`country:${country}`);
  if (city) filterParts.push(`city:${city}`);
  
  if (filterParts.length > 0) {
    searchParams.filters = filterParts.join(' AND ');
  }
  
  return await index.search(query, searchParams);
}

过滤器工具函数 #

过滤器构建器 #

javascript
class FilterBuilder {
  constructor() {
    this.filters = [];
  }
  
  equals(field, value) {
    this.filters.push(`${field}:${JSON.stringify(value)}`);
    return this;
  }
  
  notEquals(field, value) {
    this.filters.push(`${field} != ${JSON.stringify(value)}`);
    return this;
  }
  
  in(field, values) {
    const conditions = values.map(v => `${field}:${JSON.stringify(v)}`);
    this.filters.push(`(${conditions.join(' OR ')})`);
    return this;
  }
  
  range(field, min, max) {
    const conditions = [];
    if (min !== undefined) conditions.push(`${field} >= ${min}`);
    if (max !== undefined) conditions.push(`${field} <= ${max}`);
    this.filters.push(`(${conditions.join(' AND ')})`);
    return this;
  }
  
  greaterThan(field, value) {
    this.filters.push(`${field} > ${value}`);
    return this;
  }
  
  lessThan(field, value) {
    this.filters.push(`${field} < ${value}`);
    return this;
  }
  
  boolean(field, value) {
    this.filters.push(`${field}:${value}`);
    return this;
  }
  
  build() {
    return this.filters.join(' AND ');
  }
}

// 使用
const builder = new FilterBuilder();
const filters = builder
  .in('brand', ['Apple', 'Samsung'])
  .range('price', 500, 1000)
  .boolean('inStock', true)
  .greaterThan('rating', 4)
  .build();
// 结果: "(brand:Apple OR brand:Samsung) AND (price >= 500 AND price <= 1000) AND inStock:true AND rating > 4"

总结 #

过滤与筛选要点:

要点 说明
filters 通用布尔表达式过滤
facetFilters 简单分面过滤
numericFilters 数值过滤
tagFilters 标签过滤
optionalFilters 可选过滤(影响排名)
安全性 转义用户输入
性能 优先使用facetFilters

接下来,让我们学习 分页与排序

最后更新:2026-03-28