索引字段说明v2.md 11 KB

SPU-SKU索引方案选型

  1. spu为单位。SKU字段展开作为SPU属性 1.1 索引方案 除了title, brielf description seo相关 cate tags vendor所有影响相关性的字段都在spu。 sku只有款式、价格、重量、库存等相关属性。所以,可以以spu为单位建立索引。 sku中需要参与搜索的属性(比如价格、库存)展开到spu。 sku的所有需要返回的字段作为nested字段,仅用于返回。 灌入数据准备 def build_product_document(product, skus):

    提取价格列表(转换为float,保留两位小数)

    price_list = [float(sku.price) for sku in skus if sku.price is not None]

    提取重量信息(重量转为int,单位统一为克;重量+单位拼接为字符串)

    weight_list = [int(float(sku.weight) * 1000) for sku in skus if sku.weight is not None] # 转为整数克 weight_with_unit_list = [f"{sku.weight}{sku.weight_unit}" for sku in skus if sku.weight and sku.weight_unit]

    计算库存总和

    total_stock = sum([sku.inventory_quantity for sku in skus if sku.inventory_quantity is not None])

    计算价格区间

    min_price = min(price_list) if price_list else 0.0 max_price = max(price_list) if price_list else 0.0

    return { "spu_id": str(product.id), "title": product.title,

    # SPU级别的选项名称定义(如:颜色、尺码、材质)
    "option1_name": getattr(product, 'option1', None),
    "option2_name": getattr(product, 'option2', None),
    "option3_name": getattr(product, 'option3', None),
    
    # SKU搜索字段(展开)
    # 价格(int)、重量(int)、重量单位拼接重量(keyword),都以list形式灌入
    "sku_prices": price_list,  # 所有SKU价格列表,用于范围聚合
    "sku_weights": weight_list,  # 重量数值列表(转换为整数克)
    "sku_weight_units": weight_with_unit_list,  # 重量+单位字符串列表
    
    # 库存总和 将SKU的库存加起来作为一个值灌入
    "total_inventory": total_stock,  # SKU库存总和
    
    # 售价,灌入3个字段:SKU价格列表、最高价、最低价
    "min_price": min_price,  # 最低售价
    "max_price": max_price,  # 最高售价
    "price_range": {  # 价格区间对象,便于范围查询
        "gte": min_price,
        "lte": max_price
    },
    
    # SKU详细信息(nested结构,仅用于返回)
    "skus": [
        {
            "sku_id": str(sku.id),
            "price": float(sku.price) if sku.price else 0.0,
            "compare_at_price": float(sku.compare_at_price) if sku.compare_at_price else None,
            "sku_code": sku.sku,
            "stock": sku.inventory_quantity,
            "weight": float(sku.weight) if sku.weight else None,
            "weight_unit": sku.weight_unit,
    
            # SKU级别的选项值(对应SPU的选项名称)
            "option1_value": sku.option1,
            "option2_value": sku.option2,
            "option3_value": sku.option3,
    
            "image_src": sku.image_src
        }
        for sku in skus
    ],
    
    # 其他SPU级别字段(根据索引文档补充)
    "tenant_id": str(product.tenant_id),
    "brief": product.brief,
    "description": product.description,
    "vendor": product.vendor,
    "category": product.category,
    "tags": product.tags.split(',') if product.tags else [],
    "seo_title": product.seo_title,
    "seo_description": product.seo_description,
    "seo_keywords": product.seo_keywords.split(',') if product.seo_keywords else [],
    "image_url": product.image_src,
    "create_time": product.create_time.isoformat() if product.create_time else None,
    "update_time": product.update_time.isoformat() if product.update_time else None
    

    } 索引定义 { "mappings": { "properties": { "tenant_id": { "type": "keyword" }, "spu_id": { "type": "keyword" }, // 文本相关性相关字段 "title_zh": { "type": "text", "analyzer": "hanlp_index", "search_analyzer": "hanlp_standard" }, "brief_zh": { "type": "text", "analyzer": "hanlp_index", "search_analyzer": "hanlp_standard" }, "description_zh": { "type": "text", "analyzer": "hanlp_index", "search_analyzer": "hanlp_standard" }, "vendor_zh": { "type": "text", "analyzer": "hanlp_index", "search_analyzer": "hanlp_standard", "fields": { "keyword": { "type": "keyword", "normalizer": "lowercase" } } },

    "title_en": { "type": "text", "analyzer": "english", "search_analyzer": "english", }, "brief_en": { "type": "text", "analyzer": "english", "search_analyzer": "english",

    }, "description_en": { "type": "text", "analyzer": "english", "search_analyzer": "english", }, "vendor_en": { "type": "text", "analyzer": "english", "search_analyzer": "english", "fields": { "keyword": { "type": "keyword", "normalizer": "lowercase" } } },

    "tags": { "type": "keyword", },

    "min_price": { "type": "float" }, "max_price": { "type": "float" }, "compare_at_price": { "type": "float" }, "sku_prices": { "type": "float" }, "sku_weights": { "type": "long" }, "sku_weight_units": { "type": "keyword" }, "total_inventory": { "type": "long" },

    "image_url": { "type": "keyword", "index": false },

    "title_embedding": { "type": "dense_vector", "dims": 1024, "index": true, "similarity": "dot_product" },

    "create_time": { "type": "date" }, "update_time": { "type": "date" },

    "option1_name": { "type": "keyword" }, "option2_name": { "type": "keyword" }, "option3_name": { "type": "keyword" },

    "skus": { "type": "nested", "properties": { "sku_id": { "type": "keyword" }, "price": { "type": "float" }, "compare_at_price": { "type": "float" }, "sku_code": { "type": "keyword" }, "stock": { "type": "long" }, "weight": { "type": "float" }, "weight_unit": { "type": "keyword" }, "option1_value": { "type": "keyword" }, "option2_value": { "type": "keyword" }, "option3_value": { "type": "keyword" }, "image_src": { "type": "keyword", "index": false } } } } } } 1.2 查询方案 对数组字段使用 dis_max,只取最高分,避免累加。 其他重点字段

  2. Sku title

  3. category 2.1 Mysql 在spu表中: Field Type category varchar(255) category_id bigint(20) category_google_id bigint(20) category_level int(11) category_path varchar(500) 2.2 ES索引 2.2.1 输入数据 设计 1,2,3级分类 三个字段,的 category (原始文本) 2.2.2 索引方法 设计要求:

    1. 支持facet(精确过滤、keyword聚合),并且性能需要足够高。
    2. 支持普通搜索模糊匹配(用户原始query可能包括分类词)。
    3. 模糊匹配要考虑多语言 方案:采用方案2
    4. categoryPath索引 + Prefix 查询(categoryPath.keyword: "服装/男装")(如果满足条件的key太多的则性能较差,比如 查询的是一级类目,类目树叶子节点太多时性能较差)
    5. categoryPath支撑模糊查询 和 多级cate keyword索引支撑精确查询。 索引阶段冗余,查询性能高。 "category_path_zh": { // 提供模糊查询功能,辅助相关性计算 "type": "text", "analyzer": "hanlp_index", "search_analyzer": "hanlp_standard" }, "category_path_en": { // 提供模糊查询功能,辅助相关性计算 "type": "text", "analyzer": "english", "search_analyzer": "english" }, "category_path": { // 用于多层级的筛选、精确匹配 "type": "keyword", "normalizer": "lowercase"
      }, "category_id": { "type": "keyword" }, "category_name": { "type": "keyword" }, "category_level": { "type": "integer" }, "category1_name": { // 不同层级下 可能有同名的情况,因此提供一二三级分开的查询方式 "type": "keyword" }, "category2_name": { "type": "keyword" }, "category3_name": { "type": "keyword" },
  4. tags 3.1 数据源 多值 标签 最多输入250个标签,每个不得超过500字符,多个标签请用「英文逗号」隔开 新品,热卖,爆款 耳机,头戴式,爆款

分割后 list形式灌入 3.2 Mysql 3.3 ES索引 3.3.1 输入数据 3.3.2 索引方法

  1. 供应商 4.1 数据源 4.2 Mysql 4.3 ES索引 4.3.1 输入数据 4.3.2 索引方法
  2. 款式/选项值(options) 5.1 数据源 以下区域字段,商品属性为M(商品主体)的行需填写款式名称,商品属性为P(子款式)的行需填写款式值信息,商品属性为S(单一款式商品)的行无需填写
    款式1 款式2 款式3 最多255字符 最多255字符 最多255字符 SIZE COLOR
    S red
    ... 5.2 Mysql
  3. API 在 SPU 的维度直接返回3个属性定义,存储在 shoplazza_product_option 中:
  4. API在 SKU的维度直接返回3个属性值,存储在 shoplazza_product_sku 表的 option 相关的字段中: 5.3 ES索引 5.3.1 3nested,支持超过3个属性(动态)。只用作返回,不能查询。节省索引空间 "specifications": { "type": "nested", "properties": { "name": { "type": "keyword","index": false }, "value": { "type": "keyword","index": false } } },

  5. SEO相关字段 6.1 数据源 SEO标题 SEO描述 SEO URL Handle SEO URL 重定向 SEO关键词 最多5000字符 最多5000字符 "最多支持输入255字符 (SEO URL handle只对SEO URL的「URL参数」部分进行更改,即“products/”后的内容,如:products/「URL参数」 )" "创建URL重定向,访问修改前链接可跳转到修改后的新链接页面 「Y」:TRUE 「N」:FALSE " 多个关键词请用「英文逗号」隔开

6.2 Mysql 6.3 ES索引 6.3.1 输入数据 6.3.2 索引方法