You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Flask与Flask-SQLAlchemy的商品搜索功能实现咨询

商品多条件搜索实现方案(Flask + Flask-SQLAlchemy + Postgres)

一、先做搜索词到字段的映射配置

把数据库固定字段的可选值(如Collection、Category、Brand的枚举值)整理成关键词映射字典,统一处理用户输入的大小写、空格问题:

# 关键词到数据库字段的映射(键为用户可能输入的小写关键词,值为(字段名, 数据库存储值))
SEARCH_FIELD_MAPPING = {
    # Collection 对应关键词
    'men': ('collection', 'Men'),
    'women': ('collection', 'Women'),
    'kids': ('collection', 'Kids'),
    # Category 对应关键词
    'tee-shirts': ('category', 'Tee-Shirts'),
    'polos': ('category', 'Polos'),
    'bags': ('category', 'Bags & Accessories'),
    'shoes': ('category', 'Shoes'),
    # Brand 对应关键词
    'zara': ('brand', 'Zara'),
    'massimo dutti': ('brand', 'Massimo Dutti'),
    # 可根据业务扩展更多关键词
}

二、解析搜索词,拆分条件组

用户输入可能包含单组条件(如"men tee-shirts Zara")或多组条件(如"Zara bags and Massimo Dutti shoes"),先按and拆分条件组,再逐个组匹配关键词到字段:

def parse_search_query(query_str):
    query_lower = query_str.lower().strip()
    # 按and拆分多组条件
    condition_groups = [group.strip() for group in query_lower.split('and') if group.strip()]
    
    parsed_conditions = []
    for group in condition_groups:
        words = group.split()
        group_conditions = {}
        i = 0
        while i < len(words):
            # 优先匹配多词关键词(如massimo dutti)
            if i + 1 < len(words):
                two_word_key = f"{words[i]} {words[i+1]}"
                if two_word_key in SEARCH_FIELD_MAPPING:
                    field, value = SEARCH_FIELD_MAPPING[two_word_key]
                    group_conditions[field] = value
                    i += 2
                    continue
            # 匹配单词关键词
            if words[i] in SEARCH_FIELD_MAPPING:
                field, value = SEARCH_FIELD_MAPPING[words[i]]
                group_conditions[field] = value
            i += 1
        if group_conditions:
            parsed_conditions.append(group_conditions)
    return parsed_conditions

示例:输入"Zara bags and Massimo Dutti shoes"会返回:

[{'brand': 'Zara', 'category': 'Bags & Accessories'}, {'brand': 'Massimo Dutti', 'category': 'Shoes'}]

三、用Flask-SQLAlchemy构建ORM查询

每个条件组内部是AND关系,组与组之间是OR关系,用ORM构建查询:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class Product(db.Model):
    __tablename__ = 'products'
    id = db.Column(db.Integer, primary_key=True)
    brand = db.Column(db.String(100))
    title = db.Column(db.String(200))
    description = db.Column(db.Text)
    collection = db.Column(db.String(50))
    division = db.Column(db.String(100))
    category = db.Column(db.String(100))
    price = db.Column(db.Float)
    size_id = db.Column(db.Integer, db.ForeignKey('sizes.id'))
    size = db.relationship('Size', backref='products')

def search_products(query_str, page=1, per_page=20):
    parsed_conditions = parse_search_query(query_str)
    if not parsed_conditions:
        return db.paginate(Product.query, page=page, per_page=per_page, error_out=False)
    
    # 构建OR条件集合,每个元素是一组AND条件
    or_conditions = []
    for group in parsed_conditions:
        and_clauses = []
        for field, value in group.items():
            column = getattr(Product, field)
            and_clauses.append(column == value)
        or_conditions.append(db.and_(*and_clauses))
    
    # 组合查询并分页
    query = Product.query.filter(db.or_(*or_conditions))
    return query.paginate(page=page, per_page=per_page, error_out=False)

调用示例:search_products("men tee-shirts Zara")会返回符合Collection=Men、Category=Tee-Shirts、Brand=Zara的商品分页结果。

四、性能优化方案

1. 添加字段索引

给常用过滤字段添加单字段或复合索引,加速Postgres查询:

class Product(db.Model):
    __tablename__ = 'products'
    # 单字段索引
    brand = db.Column(db.String(100), index=True)
    collection = db.Column(db.String(50), index=True)
    category = db.Column(db.String(100), index=True)
    # 复合索引(针对高频组合查询,如品牌+分类)
    __table_args__ = (
        db.Index('idx_products_brand_category', 'brand', 'category'),
    )
    # 其他字段定义...

2. 用Postgres全文搜索支持模糊匹配

如果需要支持不完整关键词(如输入"zar"匹配Zara),可以用Postgres全文搜索:

-- 创建全文索引(包含品牌、分类、品类字段)
CREATE INDEX idx_products_fulltext ON products USING gin(to_tsvector('english', brand || ' ' || collection || ' ' || category));

对应的ORM查询:

def search_products_fulltext(query_str, page=1, per_page=20):
    search_tsquery = db.func.to_tsquery('english', query_str.lower())
    query = Product.query.filter(
        db.func.to_tsvector('english', Product.brand || ' ' || Product.collection || ' ' || Product.category).match(search_tsquery)
    )
    return query.paginate(page=page, per_page=per_page, error_out=False)

3. 强制分页

所有查询都添加分页逻辑,避免一次性返回大量数据拖慢接口响应。

五、扩展建议

  • 动态维护关键词映射:把关键词和字段的对应关系存到数据库,定期加载到内存,方便新增品牌、分类时无需修改代码。
  • 添加排序规则:按匹配字段数量、销量、价格等对结果排序,提升搜索体验。
  • 输入预处理:过滤标点符号、替换同义词(如"t-shirt"和"tee-shirts"视为同一关键词)。

内容的提问来源于stack exchange,提问作者Nacer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:49:54