Skip to content

Commit b467eb4

Browse files
authored
Merge branch 'main' into 1.32/add-replica-movement-functionality
2 parents 4b1b20e + 43679b7 commit b467eb4

File tree

13 files changed

+332
-6
lines changed

13 files changed

+332
-6
lines changed

src/alias/index.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { ConnectionREST } from '../index.js';
2+
import { WeaviateAlias, WeaviateAliasResponse } from '../openapi/types.js';
3+
import { Alias, AliasListAllOptions, CreateAliasArgs, UpdateAliasArgs } from './types.js';
4+
5+
export interface Aliases {
6+
/**
7+
* Create alias for a collection.
8+
*
9+
* The collection must exist prior to aliasing it.
10+
* One alias cannot be created for multiple collections simultaneously.
11+
*
12+
* @param {string} args.collection Original collection name.
13+
* @param {string} args.alias Alias for collection.
14+
* @returns {Promise<void>} Awaitable promise.
15+
* */
16+
create: (args: CreateAliasArgs) => Promise<void>;
17+
18+
/**
19+
* List all aliases defined in the schema.
20+
*
21+
* @param {string | undefined} [opts.collection] Get all aliases defined for this collection.
22+
* @returns {Promise<Alias[] | undefined>} An array of aliases.
23+
*/
24+
listAll: (opts?: AliasListAllOptions) => Promise<Alias[] | undefined>;
25+
26+
/**
27+
* Get information about an alias.
28+
*
29+
* @param {string} alias Alias to fetch.
30+
* @return {Promise<Alias>} Alias definition.
31+
*/
32+
get: (alias: string) => Promise<Alias>;
33+
34+
/**
35+
* Replace target collection the alias points to.
36+
*
37+
* To change the alias that points to the collection,
38+
* delete the alias and create a new one.
39+
*
40+
* @param {string} args.alias Alias to update.
41+
* @param {string} args.collection New collection the alias should point to.
42+
* @return {Promise<void>} Awaitable promise.
43+
*/
44+
update: (args: UpdateAliasArgs) => Promise<void>;
45+
46+
/**
47+
* Delete a collection alias.
48+
*
49+
* @param {string} alias Alias definition to delete.
50+
* @return {Promise<void>} Awaitable promise.
51+
*/
52+
delete: (alias: string) => Promise<void>;
53+
}
54+
55+
const alias = (connection: ConnectionREST): Aliases => {
56+
return {
57+
create: (args: CreateAliasArgs) =>
58+
connection.postReturn<WeaviateAlias, void>(`/aliases/`, { ...args, class: args.collection }),
59+
listAll: (opts?: AliasListAllOptions) =>
60+
connection
61+
.get<WeaviateAliasResponse>(
62+
`/aliases${opts?.collection !== undefined ? '/?class=' + opts.collection : ''}`
63+
)
64+
.then((aliases) =>
65+
aliases.aliases !== undefined
66+
? aliases.aliases.map((alias) => ({ alias: alias.alias, collection: alias.class }))
67+
: []
68+
),
69+
get: (alias: string) =>
70+
connection
71+
.get<WeaviateAlias>(`/aliases/${alias}`)
72+
.then((alias) => ({ alias: alias.alias!, collection: alias.class! })),
73+
update: (args: UpdateAliasArgs) =>
74+
connection.put(`/aliases/${args.alias}`, { class: args.newTargetCollection }),
75+
delete: (alias: string) => connection.delete(`/aliases/${alias}`, null),
76+
};
77+
};
78+
79+
export default alias;

src/alias/journey.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import weaviate, { WeaviateClient } from '..';
2+
import { requireAtLeast } from '../../test/version';
3+
import { Alias } from './types';
4+
5+
requireAtLeast(1, 32, 0).describe('manages collection aliases', () => {
6+
let client: WeaviateClient;
7+
const collectionsWithAliases = ['PaulHewson', 'GeorgeBarnes', 'ColsonBaker'];
8+
9+
beforeAll(async () => {
10+
client = await weaviate.connectToLocal();
11+
await Promise.all(collectionsWithAliases.map(client.collections.delete));
12+
await Promise.all(collectionsWithAliases.map((name) => client.collections.create({ name })));
13+
});
14+
15+
it('should create alias', () => {
16+
return Promise.all([
17+
client.alias.create({ collection: 'PaulHewson', alias: 'Bono' }),
18+
client.alias.create({ collection: 'GeorgeBarnes', alias: 'MachineGunKelly' }),
19+
])
20+
.then(() => client.alias.listAll())
21+
.then((aliases) => {
22+
expect(aliases).not.toBeUndefined();
23+
expect(aliases).toHaveLength(2);
24+
expect(aliases).toEqual<Alias[]>([
25+
{ collection: 'PaulHewson', alias: 'Bono' },
26+
{ collection: 'GeorgeBarnes', alias: 'MachineGunKelly' },
27+
]);
28+
});
29+
});
30+
31+
it('should update alias', () => {
32+
return client.alias
33+
.update({ alias: 'MachineGunKelly', newTargetCollection: 'ColsonBaker' })
34+
.then(() => client.alias.get('MachineGunKelly'))
35+
.then((alias) => {
36+
expect(alias.collection).toEqual('ColsonBaker');
37+
});
38+
});
39+
40+
it('should delete alias Bono', () => {
41+
return client.alias
42+
.delete('Bono')
43+
.then(() => client.alias.listAll({ collection: 'PaulHewson' }))
44+
.then((aliases) => expect(aliases).toEqual([]));
45+
});
46+
47+
it('should delete alias MachineGunKelly', () => {
48+
return client.alias
49+
.delete('MachineGunKelly')
50+
.then(() => client.alias.listAll({ collection: 'ColsonBaker' }))
51+
.then((aliases) => expect(aliases).toEqual([]));
52+
});
53+
});

src/alias/types.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export type Alias = {
2+
collection: string;
3+
alias: string;
4+
};
5+
6+
export type CreateAliasArgs = {
7+
collection: string;
8+
alias: string;
9+
};
10+
11+
export type UpdateAliasArgs = {
12+
newTargetCollection: string;
13+
alias: string;
14+
};
15+
16+
export type AliasListAllOptions = {
17+
collection?: string | undefined;
18+
};

src/collections/config/types/vectorizer.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export type Vectorizer =
2525
| Multi2VecPalmVectorizer
2626
| 'multi2vec-google'
2727
| 'multi2vec-jinaai'
28+
| 'multi2multivec-jinaai'
2829
| 'multi2vec-voyageai'
2930
| 'ref2vec-centroid'
3031
| 'text2vec-aws'
@@ -190,6 +191,19 @@ export type Multi2VecGoogleConfig = {
190191
};
191192
};
192193

194+
/** The configuration for multi-media-to-multi-vector vectorization using
195+
* the jina-embeddings-v4 model
196+
*
197+
* See the [documentation](https://weaviate.io/developers/weaviate/model-providers/jinaai/embeddings-multimodal) for detailed usage.
198+
*/
199+
export type Multi2MultivecJinaAIConfig = {
200+
/** The image fields used when vectorizing. */
201+
imageFields?: string[];
202+
203+
/** The text fields used when vectorizing. */
204+
textFields?: string[];
205+
};
206+
193207
/** The configuration for multi-media vectorization using the Jina module.
194208
*
195209
* See the [documentation](https://weaviate.io/developers/weaviate/model-providers/jinaai/embeddings-multimodal) for detailed usage.
@@ -205,7 +219,11 @@ export type Multi2VecJinaAIConfig = {
205219
model?: string;
206220
/** The text fields used when vectorizing. */
207221
textFields?: string[];
208-
/** Whether the collection name is vectorized. */
222+
/**
223+
* Whether the collection name is vectorized.
224+
*
225+
* @deprecated This parameter is not applicable and has no effect on the underlying module.
226+
* */
209227
vectorizeCollectionName?: boolean;
210228
/** The weights of the fields used for vectorization. */
211229
weights?: {
@@ -525,6 +543,7 @@ export type VectorizerConfig =
525543
| Multi2VecBindConfig
526544
| Multi2VecGoogleConfig
527545
| Multi2VecJinaAIConfig
546+
| Multi2MultivecJinaAIConfig
528547
| Multi2VecPalmConfig
529548
| Multi2VecVoyageAIConfig
530549
| Ref2VecCentroidConfig
@@ -556,6 +575,8 @@ export type VectorizerConfigType<V> = V extends 'img2vec-neural'
556575
? Multi2VecGoogleConfig
557576
: V extends 'multi2vec-jinaai'
558577
? Multi2VecJinaAIConfig | undefined
578+
: V extends 'multi2multivec-jinaai'
579+
? Multi2MultivecJinaAIConfig | undefined
559580
: V extends Multi2VecPalmVectorizer
560581
? Multi2VecPalmConfig
561582
: V extends 'multi2vec-voyageai'

src/collections/configure/types/vectorizer.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ export type Multi2VecCohereConfigCreate = {
160160
vectorizeCollectionName?: boolean;
161161
};
162162

163+
export type Multi2MultivecJinaAIConfigCreate = {
164+
/** The image fields to use in vectorization. */
165+
imageFields?: string[];
166+
/** The text fields to use in vectorization. */
167+
textFields?: string[];
168+
};
169+
163170
export type Multi2VecJinaAIConfigCreate = {
164171
/** The base URL to use where API requests should go. */
165172
baseURL?: string;
@@ -262,6 +269,8 @@ export type VectorizerConfigCreateType<V> = V extends 'img2vec-neural'
262269
? Multi2VecBindConfigCreate | undefined
263270
: V extends 'multi2vec-jinaai'
264271
? Multi2VecJinaAIConfigCreate | undefined
272+
: V extends 'multi2multivec-jinaai'
273+
? Multi2MultivecJinaAIConfigCreate | undefined
265274
: V extends 'multi2vec-palm'
266275
? Multi2VecPalmConfigCreate
267276
: V extends 'multi2vec-google'

src/collections/configure/unit.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { requireAtLeast } from '../../../test/version.js';
12
import {
23
GenerativeAWSConfig,
34
GenerativeAnthropicConfig,
@@ -702,6 +703,28 @@ describe('Unit testing of the vectorizer factory class', () => {
702703
});
703704
});
704705

706+
requireAtLeast(1, 32, 0).it('should create the correct Multi2MultivecJinaAIConfig with values', () => {
707+
const config = configure.multiVectors.multi2VecJinaAI({
708+
name: 'multi-jina',
709+
imageFields: ['field1', 'field2'],
710+
textFields: ['field3', 'field4'],
711+
});
712+
expect(config).toEqual<VectorConfigCreate<never, string, 'hnsw', 'multi2multivec-jinaai'>>({
713+
name: 'multi-jina',
714+
vectorIndex: {
715+
name: 'hnsw',
716+
config: undefined,
717+
},
718+
vectorizer: {
719+
name: 'multi2multivec-jinaai',
720+
config: {
721+
imageFields: ['field1', 'field2'],
722+
textFields: ['field3', 'field4'],
723+
},
724+
},
725+
});
726+
});
727+
705728
it('should create the correct Multi2VecPalmConfig type using deprecated method with defaults', () => {
706729
const config = configure.vectors.multi2VecPalm({
707730
projectId: 'project-id',

src/collections/configure/vectorizer.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ export const vectors = {
265265
},
266266
});
267267
},
268+
268269
/**
269270
* Create a `VectorConfigCreate` object with the vectorizer set to `'multi2vec-jinaai'`.
270271
*
@@ -848,4 +849,25 @@ export const multiVectors = {
848849
true
849850
);
850851
},
852+
853+
/**
854+
* Create a `VectorConfigCreate` object with the vectorizer set to `'multi2multivec-jinaai'`.
855+
*
856+
* See the [documentation](https://weaviate.io/developers/weaviate/model-providers/jinaai/embeddings-multimodal) for detailed usage.
857+
*
858+
* @param {ConfigureNonTextVectorizerOptions<N, I, 'multi2multivec-jinaai'>} [opts] The configuration options for the `multi2multivec-jinaai` vectorizer.
859+
* @returns {VectorConfigCreate<PrimitiveKeys<T>[], N, I, 'multi2multivec-jinaai'>} The configuration object.
860+
*/
861+
multi2VecJinaAI: <N extends string | undefined = undefined, I extends VectorIndexType = 'hnsw'>(
862+
opts?: ConfigureNonTextVectorizerOptions<N, I, 'multi2multivec-jinaai'>
863+
): VectorConfigCreate<never, N, I, 'multi2multivec-jinaai'> => {
864+
const { name, vectorIndexConfig, ...config } = opts || {};
865+
return makeVectorizer(name, {
866+
vectorIndexConfig,
867+
vectorizerConfig: {
868+
name: 'multi2multivec-jinaai',
869+
config,
870+
},
871+
});
872+
},
851873
};

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { LiveChecker, OpenidConfigurationGetter, ReadyChecker } from './misc/ind
3838

3939
import weaviateV2 from './v2/index.js';
4040

41+
import alias, { Aliases } from './alias/index.js';
4142
import filter from './collections/filters/index.js';
4243
import { ConsistencyLevel } from './data/replication.js';
4344
import users, { Users } from './users/index.js';
@@ -102,6 +103,7 @@ export type ClientParams = {
102103
};
103104

104105
export interface WeaviateClient {
106+
alias: Aliases;
105107
backup: Backup;
106108
cluster: Cluster;
107109
collections: Collections;
@@ -224,6 +226,7 @@ async function client(params: ClientParams): Promise<WeaviateClient> {
224226
});
225227

226228
const ifc: WeaviateClient = {
229+
alias: alias(connection),
227230
backup: backup(connection),
228231
cluster: cluster(connection),
229232
collections: collections(connection, dbVersionSupport),

src/openapi/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,8 @@ export type WeaviateReplicationType = definitions['ReplicationReplicateDetailsRe
8080
export type WeaviateReplicateRequest = definitions['ReplicationReplicateReplicaRequest'];
8181
export type WeaviateReplicateResponse = definitions['ReplicationReplicateReplicaResponse'];
8282
export type WeaviateReplicationResponse = definitions['ReplicationReplicateDetailsReplicaResponse'];
83+
// Alias
84+
export type WeaviateAlias = definitions['Alias'];
85+
export type WeaviateAliasResponse = {
86+
aliases?: Required<Exclude<definitions['AliasResponse']['aliases'], undefined>[0]>[] | undefined;
87+
};

src/roles/index.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Role as WeaviateRole,
66
} from '../openapi/types.js';
77
import {
8+
AliasPermission,
89
BackupsPermission,
910
ClusterPermission,
1011
CollectionsPermission,
@@ -150,6 +151,33 @@ const roles = (connection: ConnectionREST): Roles => {
150151
};
151152

152153
export const permissions = {
154+
/**
155+
* Create a set of permissions specific to Weaviate's collection aliasing functionality.
156+
*
157+
* @param {string | string[]} [args.alias] Aliases that will be associated with these permissions.
158+
* @returns {AliasPermission[]} The permissions for the specified aliases.
159+
*/
160+
aliases: (args: {
161+
alias: string | string[];
162+
collection: string | string[];
163+
create?: boolean;
164+
read?: boolean;
165+
update?: boolean;
166+
delete?: boolean;
167+
}): AliasPermission[] => {
168+
const aliases = Array.isArray(args.alias) ? args.alias : [args.alias];
169+
const collections = Array.isArray(args.collection) ? args.collection : [args.collection];
170+
const combinations = aliases.flatMap((alias) => collections.map((collection) => ({ alias, collection })));
171+
return combinations.map(({ collection, alias }) => {
172+
const out: AliasPermission = { alias, collection, actions: [] };
173+
if (args.create) out.actions.push('create_aliases');
174+
if (args.read) out.actions.push('read_aliases');
175+
if (args.update) out.actions.push('update_aliases');
176+
if (args.delete) out.actions.push('delete_aliases');
177+
return out;
178+
});
179+
},
180+
153181
/**
154182
* Create a set of permissions specific to Weaviate's backup functionality.
155183
*

0 commit comments

Comments
 (0)