@storecraft/database-mongodb 1.0.21 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -6
- package/index.js +5 -3
- package/migrations/00005_add_chats_collection.js +57 -0
- package/package.json +2 -3
- package/src/con.chats.js +119 -0
- package/src/con.search.js +27 -5
- package/src/con.shared.js +8 -4
- package/src/con.templates.js +53 -2
- package/tests/runner.test.js +8 -10
- package/tests/sandbox.js +5 -5
- package/vector-store/index.js +44 -9
- package/tests/query.vql.test.js +0 -24
package/README.md
CHANGED
@@ -45,16 +45,15 @@ const app = new App()
|
|
45
45
|
}
|
46
46
|
)
|
47
47
|
)
|
48
|
+
.init();
|
48
49
|
|
49
|
-
await app.
|
50
|
-
await
|
51
|
-
// create if not exists
|
52
|
-
await app.vectorstore.createVectorIndex(false, false);
|
50
|
+
await migrateToLatest(app.__show_me_everything.db, false);
|
51
|
+
await app.__show_me_everything.vector_store.createVectorIndex();
|
53
52
|
|
54
|
-
|
53
|
+
http.createServer(app.handler).listen(
|
55
54
|
8000,
|
56
55
|
() => {
|
57
|
-
|
56
|
+
app.print_banner('http://localhost:8000');
|
58
57
|
}
|
59
58
|
);
|
60
59
|
|
package/index.js
CHANGED
@@ -19,6 +19,7 @@ import { impl as storefronts } from './src/con.storefronts.js';
|
|
19
19
|
import { impl as tags } from './src/con.tags.js';
|
20
20
|
import { impl as templates } from './src/con.templates.js';
|
21
21
|
import { impl as search } from './src/con.search.js';
|
22
|
+
import { impl as chats } from './src/con.chats.js';
|
22
23
|
export { migrateToLatest } from './migrate.js';
|
23
24
|
export { MongoVectorStore } from './vector-store/index.js';
|
24
25
|
|
@@ -28,7 +29,7 @@ export { MongoVectorStore } from './vector-store/index.js';
|
|
28
29
|
export class MongoDB {
|
29
30
|
|
30
31
|
/** @satisfies {ENV<Config>} */
|
31
|
-
static EnvConfig = /** @type{const} */ ({
|
32
|
+
static EnvConfig = /** @type {const} */ ({
|
32
33
|
db_name: 'MONGODB_NAME',
|
33
34
|
url: 'MONGODB_URL',
|
34
35
|
});
|
@@ -73,8 +74,8 @@ export class MongoDB {
|
|
73
74
|
|
74
75
|
const c = this.#config;
|
75
76
|
|
76
|
-
c.db_name ??= app.
|
77
|
-
c.url ??= app.
|
77
|
+
c.db_name ??= app.env[MongoDB.EnvConfig.db_name];
|
78
|
+
c.url ??= app.env[MongoDB.EnvConfig.url] ?? 'main';
|
78
79
|
|
79
80
|
if(!this.config.db_name || !this.config.url) {
|
80
81
|
throw new Error(
|
@@ -98,6 +99,7 @@ export class MongoDB {
|
|
98
99
|
shipping_methods: shipping(this),
|
99
100
|
templates: templates(this),
|
100
101
|
search: search(this),
|
102
|
+
chats: chats(this),
|
101
103
|
}
|
102
104
|
|
103
105
|
this.#is_ready = true;
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import { Db, MongoClient } from 'mongodb';
|
2
|
+
|
3
|
+
const collections = [
|
4
|
+
'chats'
|
5
|
+
];
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @param {Db} db
|
9
|
+
* @param {MongoClient} client
|
10
|
+
*/
|
11
|
+
export async function up(db, client) {
|
12
|
+
|
13
|
+
const session = client.startSession();
|
14
|
+
try {
|
15
|
+
await session.withTransaction(async ($session) => {
|
16
|
+
for (const collection_name of collections) {
|
17
|
+
|
18
|
+
await db.createCollection(collection_name, {session: $session})
|
19
|
+
await db.collection(collection_name).dropIndexes({ session: $session });
|
20
|
+
|
21
|
+
await db.collection(collection_name).createIndexes(
|
22
|
+
[
|
23
|
+
{
|
24
|
+
key: { handle: 1 }, name: 'handle+',
|
25
|
+
background: false, unique: true, sparse: true
|
26
|
+
},
|
27
|
+
{
|
28
|
+
key: { updated_at: 1, _id: 1 }, name: '(updated_at+, _id+)',
|
29
|
+
background: false, sparse: true
|
30
|
+
},
|
31
|
+
{
|
32
|
+
key: { updated_at: -1, _id: -1 }, name: '(updated_at-, _id-)',
|
33
|
+
background: false, sparse: true
|
34
|
+
},
|
35
|
+
{
|
36
|
+
key: { search: 1 }, name: '(search+)',
|
37
|
+
background: false, sparse: true
|
38
|
+
},
|
39
|
+
], {
|
40
|
+
session: $session
|
41
|
+
}
|
42
|
+
)
|
43
|
+
}
|
44
|
+
|
45
|
+
});
|
46
|
+
} finally {
|
47
|
+
await session.endSession();
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
*
|
53
|
+
* @param {Db} db
|
54
|
+
* @param {MongoClient} client
|
55
|
+
*/
|
56
|
+
export async function down(db, client) {
|
57
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storecraft/database-mongodb",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.2.6",
|
4
4
|
"description": "Storecraft database driver for mongodb on node / bun / deno platform",
|
5
5
|
"license": "MIT",
|
6
6
|
"author": "Tomer Shalev (https://github.com/store-craft)",
|
@@ -36,8 +36,7 @@
|
|
36
36
|
"database-mongodb:docker-compose-up": "docker compose -f ./tests/docker-compose.yml up -d ",
|
37
37
|
"database-mongodb:test": "node ./tests/runner.test.js",
|
38
38
|
"test": "npm run database-mongodb:test",
|
39
|
-
"
|
40
|
-
"sc-publish": "npm publish"
|
39
|
+
"sc-publish": "npm version patch --force --no-git-tag-version && npm publish"
|
41
40
|
},
|
42
41
|
"dependencies": {
|
43
42
|
"@storecraft/core": "^1.0.0",
|
package/src/con.chats.js
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
/**
|
2
|
+
* @import { db_chats as db_col } from '@storecraft/core/database'
|
3
|
+
* @import { WithRelations } from './utils.types.js'
|
4
|
+
*/
|
5
|
+
import { Collection } from 'mongodb'
|
6
|
+
import { MongoDB } from '../index.js'
|
7
|
+
import { count_regular, get_regular, list_regular } from './con.shared.js'
|
8
|
+
import { handle_or_id, to_objid } from './utils.funcs.js';
|
9
|
+
import {
|
10
|
+
add_search_terms_relation_on, delete_me,
|
11
|
+
save_me,
|
12
|
+
} from './utils.relations.js';
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @param {MongoDB} d
|
16
|
+
* @returns {Collection<WithRelations<db_col["$type_get"]>>}
|
17
|
+
*/
|
18
|
+
const col = (d) => d.collection('chats');
|
19
|
+
|
20
|
+
/**
|
21
|
+
* @param {MongoDB} driver
|
22
|
+
* @returns {db_col["upsert"]}
|
23
|
+
*/
|
24
|
+
const upsert = (driver) => {
|
25
|
+
return async (data, search_terms=[]) => {
|
26
|
+
data = {...data};
|
27
|
+
const objid = to_objid(data.id);
|
28
|
+
const session = driver.mongo_client.startSession();
|
29
|
+
|
30
|
+
try {
|
31
|
+
await session.withTransaction(
|
32
|
+
async () => {
|
33
|
+
|
34
|
+
// SEARCH
|
35
|
+
add_search_terms_relation_on(data, search_terms);
|
36
|
+
|
37
|
+
// SAVE ME
|
38
|
+
await save_me(driver, 'chats', objid, data, session);
|
39
|
+
|
40
|
+
}
|
41
|
+
);
|
42
|
+
} catch(e) {
|
43
|
+
console.log(e);
|
44
|
+
return false;
|
45
|
+
} finally {
|
46
|
+
await session.endSession();
|
47
|
+
}
|
48
|
+
|
49
|
+
return true;
|
50
|
+
}
|
51
|
+
|
52
|
+
}
|
53
|
+
/**
|
54
|
+
* @param {MongoDB} driver
|
55
|
+
*/
|
56
|
+
const get = (driver) => get_regular(driver, col(driver));
|
57
|
+
|
58
|
+
/**
|
59
|
+
* @param {MongoDB} driver
|
60
|
+
* @returns {db_col["remove"]}
|
61
|
+
*/
|
62
|
+
const remove = (driver) => {
|
63
|
+
return async (id_or_handle) => {
|
64
|
+
const item = await col(driver).findOne(handle_or_id(id_or_handle));
|
65
|
+
|
66
|
+
if(!item) return;
|
67
|
+
|
68
|
+
const objid = to_objid(item.id)
|
69
|
+
const session = driver.mongo_client.startSession();
|
70
|
+
|
71
|
+
try {
|
72
|
+
await session.withTransaction(
|
73
|
+
async () => {
|
74
|
+
|
75
|
+
// DELETE ME
|
76
|
+
await delete_me(
|
77
|
+
driver, 'chats', objid, session
|
78
|
+
);
|
79
|
+
|
80
|
+
}
|
81
|
+
);
|
82
|
+
} catch(e) {
|
83
|
+
console.log(e);
|
84
|
+
return false;
|
85
|
+
} finally {
|
86
|
+
await session.endSession();
|
87
|
+
}
|
88
|
+
|
89
|
+
return true;
|
90
|
+
}
|
91
|
+
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
/**
|
96
|
+
* @param {MongoDB} driver
|
97
|
+
*/
|
98
|
+
const list = (driver) => list_regular(driver, col(driver));
|
99
|
+
|
100
|
+
/**
|
101
|
+
* @param {MongoDB} driver
|
102
|
+
*/
|
103
|
+
const count = (driver) => count_regular(driver, col(driver));
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @param {MongoDB} driver
|
107
|
+
* @return {db_col & { _col: ReturnType<col>}}
|
108
|
+
*/
|
109
|
+
export const impl = (driver) => {
|
110
|
+
|
111
|
+
return {
|
112
|
+
_col: col(driver),
|
113
|
+
get: get(driver),
|
114
|
+
upsert: upsert(driver),
|
115
|
+
remove: remove(driver),
|
116
|
+
list: list(driver),
|
117
|
+
count: count(driver),
|
118
|
+
}
|
119
|
+
}
|
package/src/con.search.js
CHANGED
@@ -20,7 +20,8 @@ const tables = [
|
|
20
20
|
'notifications',
|
21
21
|
'discounts',
|
22
22
|
'orders',
|
23
|
-
'templates'
|
23
|
+
'templates',
|
24
|
+
'chats'
|
24
25
|
]
|
25
26
|
|
26
27
|
/**
|
@@ -40,7 +41,23 @@ const prefix_to_resource = {
|
|
40
41
|
'tag': 'tags',
|
41
42
|
'template': 'templates',
|
42
43
|
'post': 'posts',
|
43
|
-
|
44
|
+
'chat': 'chats',
|
45
|
+
}
|
46
|
+
|
47
|
+
const resource_to_props = {
|
48
|
+
'auth_users': ['id', 'handle'],
|
49
|
+
'collections': ['id', 'handle'],
|
50
|
+
'customers': ['id', 'handle'],
|
51
|
+
'discounts': ['id', 'handle', 'title'],
|
52
|
+
'images': ['id', 'handle', 'name'],
|
53
|
+
'orders': ['id'],
|
54
|
+
'products': ['id', 'handle', 'title'],
|
55
|
+
'shipping_methods': ['id', 'handle', 'title'],
|
56
|
+
'storefronts': ['id', 'handle', 'title'],
|
57
|
+
'tags': ['id', 'handle'],
|
58
|
+
'templates': ['id', 'handle', 'title'],
|
59
|
+
'posts': ['id', 'handle', 'title'],
|
60
|
+
'chats': ['id', 'customer_email', 'customer_id'],
|
44
61
|
}
|
45
62
|
|
46
63
|
/**
|
@@ -87,10 +104,15 @@ export const quicksearch = (driver) => {
|
|
87
104
|
},
|
88
105
|
{
|
89
106
|
$project: {
|
90
|
-
title: 1,
|
91
|
-
handle: 1,
|
92
|
-
// '_relations.search': 1,
|
93
107
|
id: 1,
|
108
|
+
handle: 1,
|
109
|
+
|
110
|
+
title: 1,
|
111
|
+
name: 1,
|
112
|
+
|
113
|
+
customer_email: 1,
|
114
|
+
customer_id: 1,
|
115
|
+
|
94
116
|
_id: 0
|
95
117
|
}
|
96
118
|
}
|
package/src/con.shared.js
CHANGED
@@ -23,9 +23,10 @@ import { add_search_terms_relation_on } from './utils.relations.js'
|
|
23
23
|
* @template {Partial<withConcreteIdAndHandle<{}>>} G
|
24
24
|
* @param {MongoDB} driver
|
25
25
|
* @param {Collection<G>} col
|
26
|
+
* @param {(input: T) => T} [hook_pre_write=x=>x]
|
26
27
|
* @returns {db_crud<T, G>["upsert"]}
|
27
28
|
*/
|
28
|
-
export const upsert_regular = (driver, col) => {
|
29
|
+
export const upsert_regular = (driver, col, hook_pre_write=x=>x) => {
|
29
30
|
|
30
31
|
return async (data, search_terms=[]) => {
|
31
32
|
|
@@ -64,7 +65,7 @@ export const upsert_regular = (driver, col) => {
|
|
64
65
|
await col.insertOne(
|
65
66
|
// @ts-ignore
|
66
67
|
{
|
67
|
-
...data,
|
68
|
+
...hook_pre_write(data),
|
68
69
|
_id: data.id ? to_objid(data.id) : undefined,
|
69
70
|
},
|
70
71
|
{
|
@@ -180,9 +181,10 @@ export const expand_to_mongo_projection = (expand) => {
|
|
180
181
|
* @template T, G
|
181
182
|
* @param {MongoDB} driver
|
182
183
|
* @param {Collection<G>} col
|
184
|
+
* @param {(input: G) => G} [hook_post=x=>x]
|
183
185
|
* @returns {db_crud<T, G>["get"]}
|
184
186
|
*/
|
185
|
-
export const get_regular = (driver, col) => {
|
187
|
+
export const get_regular = (driver, col, hook_post=x=>x) => {
|
186
188
|
return async (id_or_handle, options) => {
|
187
189
|
const filter = handle_or_id(id_or_handle);
|
188
190
|
|
@@ -203,7 +205,9 @@ export const get_regular = (driver, col) => {
|
|
203
205
|
);
|
204
206
|
|
205
207
|
return /** @type {G} */(
|
206
|
-
|
208
|
+
hook_post(
|
209
|
+
/** @type {G} */(sanitize_one(res))
|
210
|
+
)
|
207
211
|
);
|
208
212
|
}
|
209
213
|
}
|
package/src/con.templates.js
CHANGED
@@ -7,6 +7,31 @@ import {
|
|
7
7
|
count_regular, get_regular, list_regular,
|
8
8
|
remove_regular, upsert_regular
|
9
9
|
} from './con.shared.js'
|
10
|
+
import { base64 } from '@storecraft/core/crypto';
|
11
|
+
|
12
|
+
/**
|
13
|
+
* @description if `base64_` prefixed then decode the postfix and return it,
|
14
|
+
* otherwise, just return the original value.
|
15
|
+
* @param {string} val
|
16
|
+
*/
|
17
|
+
const encode_base64_if_needed = val => {
|
18
|
+
if(val?.startsWith('base64_'))
|
19
|
+
return val;
|
20
|
+
|
21
|
+
return 'base64_' + base64.encode(val);
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* @description if `base64_` prefixed then decode the postfix and return it,
|
26
|
+
* otherwise, just return the original value.
|
27
|
+
* @param {string} val
|
28
|
+
*/
|
29
|
+
const decode_base64_if_needed = val => {
|
30
|
+
if(!val?.startsWith('base64_'))
|
31
|
+
return val;
|
32
|
+
|
33
|
+
return base64.decode(val.split('base64_').at(-1) ?? '');
|
34
|
+
}
|
10
35
|
|
11
36
|
/**
|
12
37
|
* @param {MongoDB} d
|
@@ -18,12 +43,38 @@ const col = (d) => d.collection('templates');
|
|
18
43
|
* @param {MongoDB} driver
|
19
44
|
* @returns {db_col["upsert"]}
|
20
45
|
*/
|
21
|
-
const upsert = (driver) => upsert_regular(
|
46
|
+
const upsert = (driver) => upsert_regular(
|
47
|
+
driver, col(driver),
|
48
|
+
(before) => {
|
49
|
+
return before && {
|
50
|
+
...before,
|
51
|
+
template_html: before?.template_html &&
|
52
|
+
encode_base64_if_needed(before?.template_html),
|
53
|
+
template_text: before?.template_text &&
|
54
|
+
encode_base64_if_needed(before?.template_text),
|
55
|
+
template_subject: before?.template_subject &&
|
56
|
+
encode_base64_if_needed(before?.template_subject),
|
57
|
+
}
|
58
|
+
},
|
59
|
+
);
|
22
60
|
|
23
61
|
/**
|
24
62
|
* @param {MongoDB} driver
|
25
63
|
*/
|
26
|
-
const get = (driver) => get_regular(
|
64
|
+
const get = (driver) => get_regular(
|
65
|
+
driver, col(driver),
|
66
|
+
(item) => {
|
67
|
+
return item && {
|
68
|
+
...item,
|
69
|
+
template_html: item?.template_html &&
|
70
|
+
decode_base64_if_needed(item?.template_html),
|
71
|
+
template_text: item?.template_text &&
|
72
|
+
decode_base64_if_needed(item?.template_text),
|
73
|
+
template_subject: item?.template_subject &&
|
74
|
+
decode_base64_if_needed(item?.template_subject),
|
75
|
+
}
|
76
|
+
}
|
77
|
+
);
|
27
78
|
|
28
79
|
/**
|
29
80
|
* @param {MongoDB} driver
|
package/tests/runner.test.js
CHANGED
@@ -8,8 +8,8 @@ import { api } from '@storecraft/core/test-runner';
|
|
8
8
|
// Main MongoDB test suite with the core test-runner for api layer
|
9
9
|
//
|
10
10
|
|
11
|
-
export const create_app =
|
12
|
-
|
11
|
+
export const create_app = () => {
|
12
|
+
return new App(
|
13
13
|
{
|
14
14
|
auth_admins_emails: ['admin@sc.com'],
|
15
15
|
auth_secret_access_token: 'auth_secret_access_token',
|
@@ -26,24 +26,22 @@ export const create_app = async () => {
|
|
26
26
|
url: process.env.MONGODB_URL,
|
27
27
|
}
|
28
28
|
)
|
29
|
-
)
|
30
|
-
|
31
|
-
return app.init()
|
29
|
+
).init();
|
32
30
|
}
|
33
31
|
|
34
32
|
async function test() {
|
35
|
-
const app =
|
33
|
+
const app = create_app();
|
36
34
|
|
37
|
-
await migrateToLatest(app.db, false);
|
35
|
+
await migrateToLatest(app._.db, false);
|
38
36
|
|
39
37
|
Object.entries(api).slice(0, -1).forEach(
|
40
38
|
([name, runner]) => {
|
41
|
-
runner.create(app).run();
|
39
|
+
runner.create(app._.app).run();
|
42
40
|
}
|
43
41
|
);
|
44
42
|
|
45
|
-
const last_test = Object.values(api).at(-1).create(app);
|
46
|
-
last_test.after(async ()=>{app.db.disconnect()});
|
43
|
+
const last_test = Object.values(api).at(-1).create(app._.app);
|
44
|
+
last_test.after(async ()=>{app._.db.disconnect()});
|
47
45
|
last_test.run();
|
48
46
|
}
|
49
47
|
|
package/tests/sandbox.js
CHANGED
@@ -16,21 +16,21 @@ export const create_app = async () => {
|
|
16
16
|
)
|
17
17
|
.withPlatform(new NodePlatform())
|
18
18
|
.withDatabase(new MongoDB({ db_name: 'test'}))
|
19
|
+
.init();
|
19
20
|
|
20
|
-
await app.
|
21
|
-
await migrateToLatest(app.db, false);
|
21
|
+
await migrateToLatest(app.__show_me_everything.db, false);
|
22
22
|
return app;
|
23
23
|
}
|
24
24
|
|
25
25
|
|
26
26
|
async function test() {
|
27
27
|
const app = await create_app();
|
28
|
-
|
29
|
-
const sf = await
|
28
|
+
const db = app.__show_me_everything.db;
|
29
|
+
const sf = await db.resources.storefronts.get_default_auto_generated_storefront()
|
30
30
|
|
31
31
|
console.log(JSON.stringify(sf, null, 2));
|
32
32
|
|
33
|
-
await
|
33
|
+
await db.disconnect();
|
34
34
|
}
|
35
35
|
|
36
36
|
test();
|
package/vector-store/index.js
CHANGED
@@ -15,6 +15,7 @@ mongo_vectorSearch_pipeline,
|
|
15
15
|
* } from 'mongodb'
|
16
16
|
* @import { ENV } from '@storecraft/core';
|
17
17
|
*/
|
18
|
+
import { truncate_or_pad_vector } from '@storecraft/core/ai/models/vector-stores/index.js';
|
18
19
|
import { Collection } from 'mongodb';
|
19
20
|
import { MongoClient, ServerApiVersion } from 'mongodb';
|
20
21
|
|
@@ -29,13 +30,12 @@ export const DEFAULT_INDEX_NAME = 'vector_store';
|
|
29
30
|
/**
|
30
31
|
* @description MongoDB Atlas Vector Store
|
31
32
|
* {@link https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-type/#:~:text=You%20can%20use%20the%20vectorSearch,to%20pre%2Dfilter%20your%20data.}
|
32
|
-
*
|
33
33
|
* @implements {VectorStore}
|
34
34
|
*/
|
35
35
|
export class MongoVectorStore {
|
36
36
|
|
37
37
|
/** @satisfies {ENV<Config>} */
|
38
|
-
static EnvConfig = /** @type{const} */ ({
|
38
|
+
static EnvConfig = /** @type {const} */ ({
|
39
39
|
db_name: 'MONGODB_VECTOR_STORE_DB_NAME',
|
40
40
|
url: 'MONGODB_VECTOR_STORE_URL'
|
41
41
|
});
|
@@ -94,10 +94,10 @@ export class MongoVectorStore {
|
|
94
94
|
|
95
95
|
/** @type {VectorStore["onInit"]} */
|
96
96
|
onInit = (app) => {
|
97
|
-
this.config.url ??= app.
|
98
|
-
?? app.
|
99
|
-
this.config.db_name ??= app.
|
100
|
-
?? app.
|
97
|
+
this.config.url ??= app.env[MongoVectorStore.EnvConfig.url]
|
98
|
+
?? app.env['MONGODB_URL'];
|
99
|
+
this.config.db_name ??= app.env[MongoVectorStore.EnvConfig.db_name]
|
100
|
+
?? app.env['MONGODB_DB_NAME'] ?? 'main';
|
101
101
|
}
|
102
102
|
|
103
103
|
/** @type {VectorStore["embedder"]} */
|
@@ -117,7 +117,9 @@ export class MongoVectorStore {
|
|
117
117
|
(doc, ix) => (
|
118
118
|
{
|
119
119
|
updated_at: new Date().toISOString(),
|
120
|
-
embedding:
|
120
|
+
embedding: truncate_or_pad_vector(
|
121
|
+
vectors[ix], this.config.dimensions
|
122
|
+
),
|
121
123
|
metadata: doc.metadata,
|
122
124
|
pageContent: doc.pageContent,
|
123
125
|
[NAMESPACE_KEY]: doc.namespace,
|
@@ -164,6 +166,13 @@ export class MongoVectorStore {
|
|
164
166
|
}
|
165
167
|
);
|
166
168
|
|
169
|
+
if(!result) {
|
170
|
+
console.warn(
|
171
|
+
'MongoVectoreStore::upsertDocuments() - no result from embedder'
|
172
|
+
);
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
|
167
176
|
const vectors = result.content;
|
168
177
|
|
169
178
|
return this.upsertVectors(
|
@@ -247,15 +256,41 @@ export class MongoVectorStore {
|
|
247
256
|
* @param {boolean} [delete_index_if_exists_before=false]
|
248
257
|
* @returns {Promise<boolean>}
|
249
258
|
*/
|
250
|
-
createVectorIndex = async (
|
259
|
+
createVectorIndex = async (
|
260
|
+
disconnect_after_finish=true,
|
261
|
+
delete_index_if_exists_before=false
|
262
|
+
) => {
|
251
263
|
if(delete_index_if_exists_before) {
|
252
264
|
await this.deleteVectorIndex();
|
253
265
|
}
|
254
|
-
|
266
|
+
|
255
267
|
const db = this.client.db(this.config.db_name);
|
256
268
|
const collection_name = this.config.index_name;
|
269
|
+
|
270
|
+
{ // skip if index already exists
|
271
|
+
const indices = await db
|
272
|
+
.collection(collection_name)
|
273
|
+
.listSearchIndexes()
|
274
|
+
.toArray();
|
275
|
+
|
276
|
+
if(indices?.length) {
|
277
|
+
const index = indices.find(
|
278
|
+
(index) => index.name === this.config.index_name
|
279
|
+
);
|
280
|
+
if(index) {
|
281
|
+
console.log('MongoVectorStore::createVectorIndex - index already exists, skipping');
|
282
|
+
if(disconnect_after_finish)
|
283
|
+
await this.client.close();
|
284
|
+
|
285
|
+
return true;
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
257
290
|
// collection name will have the same name as the index
|
258
291
|
await db.createCollection(collection_name);
|
292
|
+
|
293
|
+
|
259
294
|
const index_result = await db.collection(collection_name).createSearchIndex(
|
260
295
|
{
|
261
296
|
name: this.config.index_name,
|
package/tests/query.vql.test.js
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
import { test } from 'uvu';
|
2
|
-
import * as assert from 'uvu/assert';
|
3
|
-
import { query_vql_to_mongo_filter } from '../src/utils.query.js'
|
4
|
-
|
5
|
-
//
|
6
|
-
// TODO:
|
7
|
-
// - [ ] Add tests for query_vql_to_mongo_filter
|
8
|
-
// although it is tested as a black box in the main test file
|
9
|
-
//
|
10
|
-
test('query_vql_to_mongo_filter', async () => {
|
11
|
-
const vql_ast = {
|
12
|
-
};
|
13
|
-
|
14
|
-
const mongo = {
|
15
|
-
};
|
16
|
-
|
17
|
-
// const m1 = query_vql_to_mongo_filter(vql_ast);
|
18
|
-
|
19
|
-
// console.log(JSON.stringify(m1, null, 2))
|
20
|
-
|
21
|
-
// assert.equal(m1, mongo);
|
22
|
-
});
|
23
|
-
|
24
|
-
test.run();
|