瀏覽代碼

MongoDB 修改为单例模式

mrh 11 月之前
父節點
當前提交
5c49c7ba72
共有 4 個文件被更改,包括 79 次插入15 次删除
  1. 28 0
      docs/gpt/agent_product.md
  2. 6 9
      src/ai/agent_product.py
  3. 5 2
      src/excel_tools/file_manager.py
  4. 40 4
      src/manager/core/db_mongo.py

+ 28 - 0
docs/gpt/agent_product.md

@@ -1,3 +1,31 @@
+# 存入 mongodb
+@/src\ai\agent_product.py 
+@/src\models\product_model.py 
+@/src\manager\manager_task.py 
+分析结果: {
+  "results": [
+    {
+      "asin": "B0B658JC22",
+      "main_key": "配線カバー",
+      "monthly_searches": "35,521",
+      "reason": "该关键词在所有竞品中搜索量最高,且与产品名称'电线保护套'高度相关,符合日本市场对产品功能性的需求。"     
+    },
+    {
+      "asin": "B0B658JC22",
+      "main_key": "ケーブルカバー",
+      "monthly_searches": "16,103",
+      "reason": "搜索量排名第二,广泛用于描述电线保护产品,适合作为主要关键词之一。"
+    },
+    {
+      "asin": "B0B658JC22",
+      "main_key": "スパイラルケーブル",
+      "monthly_searches": "10,806",
+      "reason": "搜索量超过1万,且与产品的螺旋设计特点相关,适合吸引特定需求的消费者。"
+    }
+  ],
+  "supplement": "日本市场消费者对产品的功能性和设计细节有较高要求,选择搜索量高且与产品特性紧密相关的关键词有助于提高产品的可见性和吸引力。"
+}
+
 # Agent prompt template
 @/src\ai\agent_product.py 
 @/src\models\product_model.py 

+ 6 - 9
src/ai/agent_product.py

@@ -151,8 +151,7 @@ class FormatterFactory:
         raise ValueError(f"Unsupported format type: {format_type}")
 
 async def test_product_mongo(main_key_num=3, format_type: str = "json"):
-    db_mongo = BaseMongoManager()
-    await db_mongo.initialize()
+    db_mongo = BaseMongoManager()  # 自动初始化
     product = await Product.find_one(Product.basic_info.name == "电线保护套")
     product_name = product.basic_info.name
     # 使用默认配置
@@ -277,7 +276,7 @@ class AnalysisService:
         prompt = await self._prepare_prompt(product, format_type)
         return await self.llm_service.analyze(prompt)
 
-    async def _prepare_prompt(self, product: Product, format_type: str) -> str:
+    async def _prepare_prompt(self, product: Product, format_type: str, main_key_num=3) -> str:
         competitor_data = get_competitor_prompt_data(product)
         output_fields = {
             "results": {
@@ -300,12 +299,10 @@ class AnalysisService:
 竞品数据:
 {competitor_data}
 ----
-我是日本站的亚马逊运营,正在为产品 {product.basic_info.name} 选主要关键词。
-请根据以上 {len(competitor_data)} 个竞品数据,按以下规则分析:
-1. 优先选择搜索量1万以上的相同关键词
-2. 不足时选择搜索量前十且相关性强的关键词
-3. 结合日本市场特点分析
-
+我是日本站的亚马逊运营,我在给产品名称为 {product.basic_info.name} 选主要关键词,请根据以上 {len(competitor_data)} 个竞品数据,按以下规则分析:
+- 选出搜索量在1万以上的相同关键词作为主要关键词{main_key_num}个。
+- 如果竞品的搜索量都不足1万,则从排名前十的关键词中筛选 {main_key_num} 个搜索量最大且相关性最强的词。
+- 结合日本市场特点分析
 输出格式:
 {output_format}'''
 

+ 5 - 2
src/excel_tools/file_manager.py

@@ -54,9 +54,12 @@ class ExcelFileManager:
 
 async def main():
     self = ExcelFileManager(r"G:\code\amazone\copywriting_production\output\resource\multi_data.xlsx")
-    db_mongo = BaseMongoManager()
+    db_mongo = BaseMongoManager()  # 自动初始化
     await db_mongo.initialize()
-    product = await Product.find_one(Product.basic_info.name == "电线保护套")
+    product = await Product.find_one(Product.basic_info["name"] == "电线保护套")
+
+    logger.info(f"{product}")
+    return
     extract_data_lsit = product.competitor_crawl_data
     self.write_competitive_sheet(product.competitor_crawl_data)
     self.save_all()

+ 40 - 4
src/manager/core/db_mongo.py

@@ -1,3 +1,4 @@
+import asyncio
 from datetime import datetime
 from typing import Optional, List
 from beanie import Document, Indexed, init_beanie
@@ -9,11 +10,44 @@ from src.models.product_model import Product
 from beanie.operators import Set, Rename
 
 class BaseMongoManager:
+    _instance = None
+    _init_lock = asyncio.Lock()
+    _is_initialized = False
+
+    def __new__(cls):
+        if not cls._instance:
+            cls._instance = super().__new__(cls)
+            cls._instance.client = None
+            cls._instance.db = None
+        return cls._instance
+
     def __init__(self, mongo_url: str = None, db_name: str = None):
-        self.client = AsyncIOMotorClient(mongo_url or MONGO_URL)
-        self.db = self.client[db_name or MONGO_DB_NAME]
+        if not hasattr(self, 'client') or self.client is None:
+            self.client = AsyncIOMotorClient(mongo_url or MONGO_URL)
+            self.db = self.client[db_name or MONGO_DB_NAME]
+
+    async def _ensure_initialized(self):
+        """确保数据库已初始化"""
+        if not self._is_initialized:
+            await self.initialize()
+
     async def initialize(self):
-        await init_beanie(database=self.db, document_models=[Product])
+        async with self._init_lock:
+            if not self._is_initialized:
+                if not hasattr(self, 'db') or self.db is None:
+                    self.__init__()  # 确保client和db已初始化
+                await init_beanie(database=self.db, document_models=[Product])
+                self._is_initialized = True
+
+    async def check_connection(self) -> bool:
+        """检查数据库连接是否健康"""
+        if not self._is_initialized:
+            await self.initialize()
+        try:
+            await self.client.admin.command('ping')
+            return True
+        except Exception:
+            return False
 
     async def backup(self, source_collection_name: Document, backup_collection_name:str, backup_db_name: str = f"{MONGO_DB_NAME}_backup"):
         backup_db = self.client[backup_db_name]
@@ -28,10 +62,12 @@ class ProductManagerMongo(BaseMongoManager):
         return await product.insert()
 
     async def get_product(self, product_id: int) -> Optional[Product]:
+        await self._ensure_initialized()
         return await Product.find_one(Product.id == product_id)
 
     async def get_product_by_name(self, name: str) -> Optional[Product]:
-        return await Product.find_one(Product.basic_info.name == name)
+        await self._ensure_initialized()
+        return await Product.find_one(Product.basic_info["name"] == name)
     async def migrate_field():
         # 迁移字段名 competitor_analysis 到 competitor_crawl_data
         await Product.find(