Files
admin 0593ff7e62
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
数字我 Digital Me:全量入库(大文件走 Git LFS)
2026-10-10 16:24:43 +08:00

65 lines
3.3 KiB
JavaScript

// 把 MongoDB knowledge 集合里已有的向量重建进 DashVector 索引。
//
// 何时用:①首次接入 DashVector(建集合 + 灌存量向量);②补齐入库时同步失败的块(标了 vectorPending 的);
// ③换过 embedding 维度后重灌(见下"换维度")。
//
// 幂等性:本脚本用 insert 语义,只【补齐缺失】的向量、灌成功后清 vectorPending 标记。它【不覆盖】已存在
// 同 _id 的向量(在线入库每块都是全新 _id,不会撞;故正常场景无需覆盖)。
// ⚠ 换维度 / 修复"已存在但内容错"的向量:insert 不覆盖,必须【新建集合】——把 .env 的 DASHVECTOR_COLLECTION
// 改成新名(或在阿里云控制台删掉旧集合)后再跑本脚本。ensureCollection 已会在维度不符时【大声报错】提示你。
//
// 用法(服务器后端目录内,.env 里已配好 DASHVECTOR_*): node scripts/reindex-vectors.js
// MongoDB 永远是真相源,本脚本只把真相源投影进向量索引;不改动 knowledge 任何数据(仅清 vectorPending 标记)。
import 'dotenv/config';
import { connectDb, getDb, closeDb } from '../src/db.js';
import { config } from '../src/config.js';
import { vectorEnabled, ensureCollection, vectorUpsert } from '../src/services/vectorStore.js';
async function run() {
if (!vectorEnabled()) {
console.error('❌ 向量库未启用。请在 .env 配 DASHVECTOR_ENDPOINT / DASHVECTOR_API_KEY(和可选 DASHVECTOR_COLLECTION),再重跑。');
process.exit(1);
}
console.log(`向量库: DashVector · collection=${config.vector.dashvector.collection} · dim=${config.vector.dashvector.dim}`);
console.log('① 确保集合存在且就绪(维度不符会在此报错)…');
const c = await ensureCollection();
console.log(c.existed ? ' 集合已存在,复用。' : c.notReady ? ' 集合已创建(尚未就绪,后续写入会自动重试)。' : ' 集合已创建、就绪。');
await connectDb();
const db = getDb();
const cursor = db.collection('knowledge')
.find({ embedding: { $type: 'array' } })
.project({ embedding: 1, twinId: 1, sourceType: 1 })
.addCursorFlag('noCursorTimeout', true) // 大集合 + 慢/限流的 DashVector:防两次 getMore 间的阻塞 upsert 超过游标空闲超时(10min)
.batchSize(500);
let batch = [];
let ids = [];
let total = 0;
const BATCH = 200;
const flush = async () => {
if (!batch.length) return;
await vectorUpsert(batch);
// 灌成功 → 清掉这些块入库时可能打上的 vectorPending 标记(它们已进索引)。
try { await db.collection('knowledge').updateMany({ _id: { $in: ids } }, { $unset: { vectorPending: '' } }); } catch { /* 清标失败无害 */ }
total += batch.length;
process.stdout.write(`\r 已重建 ${total} 块…`);
batch = []; ids = [];
};
console.log('② 遍历 knowledge 集合,灌入向量…');
for await (const d of cursor) {
if (!Array.isArray(d.embedding) || !d.embedding.length) continue;
batch.push({ id: String(d._id), embedding: d.embedding, twinId: String(d.twinId), sourceType: d.sourceType || 'text' });
ids.push(d._id);
if (batch.length >= BATCH) await flush();
}
await flush();
console.log(`\n✅ 完成。共重建 ${total} 块向量进 DashVector。`);
await closeDb();
}
run().catch((e) => { console.error('\n❌ 重建失败:', e.message); process.exit(1); });