|
|
@@ -1,159 +1,117 @@
|
|
|
+import asyncio
|
|
|
from datetime import datetime
|
|
|
from typing import Optional, Dict, List
|
|
|
from sqlmodel import SQLModel, Field, Relationship, Column, JSON
|
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
|
from sqlalchemy import ForeignKeyConstraint
|
|
|
from pydantic import BaseModel
|
|
|
+from beanie import Document, Indexed, init_beanie
|
|
|
+from motor.motor_asyncio import AsyncIOMotorClient,AsyncIOMotorDatabase
|
|
|
|
|
|
class MarketingInfo(BaseModel):
|
|
|
"""营销信息"""
|
|
|
+ title: Optional[str] = None
|
|
|
+ st_search: Optional[str] = None
|
|
|
selling_point: Optional[List[str]] = None
|
|
|
- product_style: Optional[str] = None
|
|
|
- referent: Optional[dict] = {}
|
|
|
+ product_introduction: Optional[str] = None
|
|
|
|
|
|
-# 类目表(邻接表模式)
|
|
|
-class Category(SQLModel, table=True):
|
|
|
- id: Optional[int] = Field(default=None, primary_key=True)
|
|
|
- name: str = Field(index=True, nullable=False)
|
|
|
- parent_id: Optional[int] = Field(default=None, foreign_key="category.id")
|
|
|
- level: int = Field(default=1, description="类目层级(1级为最高)")
|
|
|
- full_path: str = Field(
|
|
|
- index=True,
|
|
|
- description="完整类目路径(如:'家居/厨房用品/餐具')"
|
|
|
- )
|
|
|
+class ProductBaseInfo(BaseModel):
|
|
|
+ """产品基本信息
|
|
|
+产品名称 电线保护套
|
|
|
+包装内容 一个/袋
|
|
|
+材质 TPU
|
|
|
+颜色 三种颜色:黑色、银色、金色
|
|
|
+尺寸 直径6MM,长度93-95CM
|
|
|
+包裹尺寸 14*17*3CM
|
|
|
+重量 30G
|
|
|
+主要用途 保护电源线,车匝线,刹车线
|
|
|
+主要卖点
|
|
|
+- 优质TPU,健康环保好看,耐磨耐脏
|
|
|
+- 耐高温防火阻燃,
|
|
|
+- 预防线管老化,延长线路使用寿命
|
|
|
+- 柔软易弯曲,可卷起来收纳
|
|
|
+ """
|
|
|
+ name: Optional[str] = None
|
|
|
+ content: Optional[str] = None
|
|
|
+ material: Optional[str] = None
|
|
|
+ color: Optional[str] = None
|
|
|
+ size: Optional[str] = None
|
|
|
+ packaging_size: Optional[str] = None
|
|
|
+ weight: Optional[str] = None
|
|
|
+ main_usage: Optional[str] = None
|
|
|
+ selling_point: Optional[List[str]] = None
|
|
|
+
|
|
|
+# 价格成本专用表(与变体一对一关系)
|
|
|
+class Variant(BaseModel):
|
|
|
+ name: Optional[str] = None
|
|
|
+ # 核心财务字段(结构化存储)
|
|
|
+ base_price: Optional[float] = None
|
|
|
+ commission_rate: Optional[float] = None
|
|
|
+ fba_fee: Optional[float] = None
|
|
|
+ cost_rmb: Optional[float] = None
|
|
|
+ logistics_cost: Optional[float] = None
|
|
|
+
|
|
|
+class CompetitorAnalysis(BaseModel):
|
|
|
+ '''竞品表'''
|
|
|
+ sql_id: Optional[int] = Field(default=None)
|
|
|
+ asin: Optional[str] = None
|
|
|
+ asin_area: Optional[str] = 'JP'
|
|
|
+ # 爬取数据的 S3 路径
|
|
|
+ extra_result_path: Optional[str] = None
|
|
|
+ mhtml_path: Optional[str] = None
|
|
|
+ error: Optional[str] = None
|
|
|
+ created_at: Optional[datetime] = Field(default_factory=datetime.now)
|
|
|
|
|
|
# 产品主表(核心实体)
|
|
|
-class Product(SQLModel, table=True):
|
|
|
- id: Optional[int] = Field(default=None, primary_key=True)
|
|
|
- title: str = Field(index=True, unique=True, nullable=False)
|
|
|
- st_search: Optional[int] = Field(default=None)
|
|
|
- # 卖点1、卖点2、产品介绍风格1、风格2、
|
|
|
+class Product(Document):
|
|
|
+ basic_info: Optional[ProductBaseInfo] = Field(
|
|
|
+ default=None,
|
|
|
+ description="产品基本信息"
|
|
|
+ )
|
|
|
marketing: Optional[MarketingInfo] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
+ default=None,
|
|
|
description="营销信息,使用JSONB存储。卖点1、卖点2、产品介绍风格1、风格2。。。")
|
|
|
|
|
|
- # 动态扩展字段(竞品主关键词分析、竞品长尾词分析)
|
|
|
- competitor_analysis: Optional[dict] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
+ competitor_analysis: Optional[List[CompetitorAnalysis]] = Field(
|
|
|
description="竞品分析信息,使用JSONB存储。竞品主关键词分析、竞品长尾词分析。。。")
|
|
|
|
|
|
- leaf_category_id: Optional[int] = Field(
|
|
|
- foreign_key="category.id",
|
|
|
- description="产品所属的末级类目ID"
|
|
|
- )
|
|
|
-
|
|
|
# 变体,如版本、型号、颜色、套餐,各个变体对应着价格、成本等财务数据
|
|
|
- variants: List["ProductVariant"] = Relationship(back_populates="product")
|
|
|
-
|
|
|
- dynamic_attributes: Optional[Dict] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
- description="动态扩展属性,使用JSONB存储"
|
|
|
- )
|
|
|
-
|
|
|
- # 对象存储引用(S3路径管理)
|
|
|
- object_ref: Optional[Dict] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
- description="S3对象引用,格式示例:{'main_image':'s3://...','attachments':[...]}"
|
|
|
+ variants: Optional[List[Variant]] = Field(
|
|
|
+ default=None,
|
|
|
+ description="产品变体信息,使用JSONB存储。如:{'color':['黑色','金色'],'size':['1m','3m']}"
|
|
|
)
|
|
|
-
|
|
|
created_at: Optional[datetime] = Field(default_factory=datetime.now)
|
|
|
updated_at: Optional[datetime] = Field(default=None)
|
|
|
|
|
|
|
|
|
-# 产品变体表(一对多关系)
|
|
|
-class ProductVariant(SQLModel, table=True):
|
|
|
- id: Optional[int] = Field(default=None, primary_key=True)
|
|
|
- product_id: int = Field(foreign_key="product.id", nullable=False)
|
|
|
- variant_name: str = Field(max_length=100, description="变体名称(如:黑色1m/金色3m)")
|
|
|
- variant_type: str = Field(
|
|
|
- default="color",
|
|
|
- max_length=20,
|
|
|
- description="变体类型:color/size/package"
|
|
|
- )
|
|
|
- # 变体属性(动态扩展)
|
|
|
- attributes: Dict = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
- description="变体属性(如颜色代码、尺寸规格)"
|
|
|
- )
|
|
|
-
|
|
|
- # 与财务数据的一对一关系
|
|
|
- financial: Optional["ProductFinancial"] = Relationship(
|
|
|
- back_populates="variant",
|
|
|
- sa_relationship_kwargs={"uselist": False}
|
|
|
+async def main():
|
|
|
+ # Beanie uses Motor async client under the hood
|
|
|
+ client = AsyncIOMotorClient("mongodb://sv-v2:27017")
|
|
|
+ # 不需要传参数据库名,直接通过 client.test 属性名的方式就能连接或创建 test 数据库
|
|
|
+ # 或者通过 client["test"] 的方式连接或创建 test 数据库
|
|
|
+ await init_beanie(database=client["amazone"], document_models=[Product])
|
|
|
+ # await insert_object()
|
|
|
+ product = Product(
|
|
|
+ basic_info=ProductBaseInfo(
|
|
|
+ name="电线保护套",
|
|
|
+ size="直径6MM,长度93-95CM",
|
|
|
+ weight="30G",
|
|
|
+ ),
|
|
|
+ marketing=MarketingInfo(
|
|
|
+
|
|
|
+ ),
|
|
|
+ competitor_analysis=[
|
|
|
+ CompetitorAnalysis(
|
|
|
+
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ variants=[
|
|
|
+ Variant(),
|
|
|
+ ],
|
|
|
)
|
|
|
+ print(product.model_dump_json(indent=2))
|
|
|
+ await product.insert()
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-# 价格成本专用表(与变体一对一关系)
|
|
|
-class ProductFinancial(SQLModel, table=True):
|
|
|
- variant_id: int = Field(
|
|
|
- default=None,
|
|
|
- foreign_key="productvariant.id",
|
|
|
- primary_key=True
|
|
|
- )
|
|
|
- # 核心财务字段(结构化存储)
|
|
|
- base_price: float = Field(nullable=False)
|
|
|
- commission_rate: float = Field()
|
|
|
- fba_fee: float = Field()
|
|
|
- cost_rmb: float = Field()
|
|
|
- logistics_cost: float = Field()
|
|
|
+if __name__ == "__main__":
|
|
|
+ asyncio.run(main())
|
|
|
|
|
|
- # 动态计算字段(JSON存储)
|
|
|
- calculation_Dict:Optional[Dict] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
- description="汇率/利润率等动态计算字段"
|
|
|
- )
|
|
|
- # 与变体的反向关系
|
|
|
- variant: Optional[ProductVariant] = Relationship(back_populates="financial")
|
|
|
-
|
|
|
-# 优化后的产品-竞品关系表
|
|
|
-class ProductCompetitorLink(SQLModel, table=True):
|
|
|
- product_id: Optional[int] = Field(
|
|
|
- default=None,
|
|
|
- foreign_key="product.id",
|
|
|
- primary_key=True
|
|
|
- )
|
|
|
- competitor_id: Optional[int] = Field(
|
|
|
- default=None,
|
|
|
- foreign_key="asinseed.id",
|
|
|
- primary_key=True
|
|
|
- )
|
|
|
- relation_type: Optional[str] = Field(
|
|
|
- default="similar",
|
|
|
- max_length=20,
|
|
|
- primary_key=True,
|
|
|
- description="关联类型:similar/alternative等"
|
|
|
- )
|
|
|
- similarity_metrics: Optional[Dict] = Field(
|
|
|
- default={},
|
|
|
- sa_column=Column(JSONB),
|
|
|
- description="相似度指标数据"
|
|
|
- )
|
|
|
- weight: float = Field(
|
|
|
- default=1.0,
|
|
|
- description="关联权重(用于多竞品对比时加权计算)"
|
|
|
- )
|
|
|
-
|
|
|
-# 增强版关键词体系
|
|
|
-class ProductKeyword(SQLModel, table=True):
|
|
|
- id: Optional[int] = Field(default=None, primary_key=True)
|
|
|
- product_id: int = Field(foreign_key="product.id", nullable=False)
|
|
|
- keyword_type: str = Field(
|
|
|
- default="main",
|
|
|
- max_length=20,
|
|
|
- description="关键词类型:main/long-tail/related"
|
|
|
- )
|
|
|
- language: str = Field(default="ja", max_length=10)
|
|
|
- keyword: str = Field(index=True, nullable=False)
|
|
|
- search_volume: Optional[int] = Field()
|
|
|
- # 关键词关联的变体(可选)
|
|
|
- variant_id: Optional[int] = Field(
|
|
|
- foreign_key="productvariant.id",
|
|
|
- description="特定变体关联的关键词"
|
|
|
- )
|