chore: 以本地为准,上传全部并替换 GitHub
This commit is contained in:
131
开发文档/6、后端/MongoDB连接器核心.md
Normal file
131
开发文档/6、后端/MongoDB连接器核心.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 神射手 - MongoDB连接器核心
|
||||
|
||||
> 📅 从 lib/mongodb.ts 提取 | 2026-01-31
|
||||
|
||||
---
|
||||
|
||||
## 一、连接配置
|
||||
|
||||
```typescript
|
||||
// lib/mongodb.ts
|
||||
const MONGODB_URI = process.env.MONGODB_URI ||
|
||||
'mongodb://admin:admin123@localhost:27017/?authSource=admin'
|
||||
|
||||
const DB_NAMES = {
|
||||
KR: 'KR',
|
||||
KR_腾讯: 'KR_腾讯',
|
||||
KR_微博: 'KR_微博',
|
||||
KR_京东: 'KR_京东',
|
||||
KR_存客宝: 'KR_存客宝',
|
||||
KR_点了码: 'KR_点了码'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、核心函数
|
||||
|
||||
### 2.1 连接池
|
||||
|
||||
```typescript
|
||||
let cachedClient: MongoClient | null = null
|
||||
|
||||
export async function getMongoClient(): Promise<MongoClient> {
|
||||
if (cachedClient) return cachedClient
|
||||
const client = new MongoClient(MONGODB_URI, {
|
||||
maxPoolSize: 10,
|
||||
minPoolSize: 2,
|
||||
maxIdleTimeMS: 60000,
|
||||
serverSelectionTimeoutMS: 5000,
|
||||
})
|
||||
await client.connect()
|
||||
cachedClient = client
|
||||
return client
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 手机号归一化
|
||||
|
||||
```typescript
|
||||
function normalizePhone(phone: string): string[] {
|
||||
const cleaned = phone.replace(/\D/g, '')
|
||||
const variants: string[] = []
|
||||
if (cleaned.startsWith('86') && cleaned.length === 13) {
|
||||
const base = cleaned.slice(2)
|
||||
variants.push(base, `+86${base}`, `86${base}`, cleaned)
|
||||
} else if (cleaned.length === 11 && cleaned.startsWith('1')) {
|
||||
variants.push(cleaned, `+86${cleaned}`, `86${cleaned}`)
|
||||
} else {
|
||||
variants.push(phone, cleaned)
|
||||
}
|
||||
return [...new Set(variants)]
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 跨库查询用户画像
|
||||
|
||||
```typescript
|
||||
export async function queryFullProfile(phone: string) {
|
||||
const client = await getMongoClient()
|
||||
const phoneVariants = normalizePhone(phone)
|
||||
const query = { $or: phoneVariants.map(p => ({ phone: p })) }
|
||||
|
||||
const [valuation, qqPhone, ckbAsset] = await Promise.all([
|
||||
client.db('KR').collection('用户估值').findOne(query),
|
||||
client.db('KR_腾讯').collection('QQ+手机').findOne(query),
|
||||
client.db('KR_存客宝').collection('用户资产统一视图').findOne(query).catch(() => null)
|
||||
])
|
||||
|
||||
return { valuation, qqPhone, ckbAsset }
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 智能搜索(QQ→手机→画像)
|
||||
|
||||
```typescript
|
||||
export async function intelligentSearch(query: string) {
|
||||
// QQ号: 先查 KR_腾讯 获取手机号,再查 KR.用户估值
|
||||
if (/^\d{5,11}$/.test(query)) {
|
||||
const qqDoc = await client.db('KR_腾讯').collection('QQ+手机').findOne({
|
||||
$or: [{ qq: query }, { qq: parseInt(query) }]
|
||||
})
|
||||
if (qqDoc?.phone) {
|
||||
return queryFullProfile(qqDoc.phone)
|
||||
}
|
||||
}
|
||||
// 手机号: 直接 queryFullProfile
|
||||
// 关键词: name/city/province 模糊搜索
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、接口定义
|
||||
|
||||
```typescript
|
||||
interface UserValuationDoc {
|
||||
phone?: string
|
||||
phone_masked?: string
|
||||
name?: string
|
||||
user_level?: string
|
||||
user_evaluation_score?: number
|
||||
province?: string
|
||||
city?: string
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
interface QQPhoneDoc {
|
||||
qq: string
|
||||
phone?: string
|
||||
手机号?: string
|
||||
省份?: string
|
||||
运营商?: string
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、关联文档
|
||||
|
||||
- [后端开发规范.md](./后端开发规范.md)
|
||||
- [../7、数据库/ER与查询逻辑.md](../7、数据库/ER与查询逻辑.md)
|
||||
Reference in New Issue
Block a user