基于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
相关产品推荐
相关产品推荐

