Skip to content

Commit c51b8f9

Browse files
Merge pull request #269506 from jcodella/patch-7
Updated to include HSNW and filtered vector search
2 parents 8986891 + 0c0f343 commit c51b8f9

File tree

1 file changed

+249
-61
lines changed

1 file changed

+249
-61
lines changed

articles/cosmos-db/mongodb/vcore/vector-search.md

Lines changed: 249 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,71 @@ Vector search is a method that helps you find similar items based on their data
2525

2626
By integrating vector search capabilities natively, you can unlock the full potential of your data in applications that are built on top of the [OpenAI API](../../../ai-services/openai/concepts/understand-embeddings.md). You can also create custom-built solutions that use vector embeddings.
2727

28-
## Use the createIndexes template to create a vector index
28+
## Create a vector index
29+
To perform vector similiarity search over vector properties in your documents, you'll have to first create a _vector index_.
2930

30-
To create a vector index, use the following `createIndexes` template:
31+
### Create a vector index using HNSW
32+
33+
You can create (Hierarchical Navigable Small World) indexes on M40 cluster tiers and higher. To create the HSNW index, you need to create a vector index with the `"kind"` parameter set to `"vector-hnsw"` following the template below:
34+
35+
```javascript
36+
{
37+
"createIndexes": "<collection_name>",
38+
"indexes": [
39+
{
40+
"name": "<index_name>",
41+
"key": {
42+
"<path_to_property>": "cosmosSearch"
43+
},
44+
"cosmosSearchOptions": {
45+
"kind": "vector-hnsw",
46+
"m": <integer_value>,
47+
"efConstruction": <integer_value>,
48+
"similarity": "<string_value>",
49+
"dimensions": <integer_value>
50+
}
51+
}
52+
]
53+
}
54+
```
55+
56+
|Field |Type |Description |
57+
|---------|---------|---------|
58+
| `index_name` | string | Unique name of the index. |
59+
| `path_to_property` | string | Path to the property that contains the vector. This path can be a top-level property or a dot notation path to the property. If a dot notation path is used, then all the nonleaf elements can't be arrays. Vectors must be a `number[]` to be indexed and return in vector search results.|
60+
| `kind` | string | Type of vector index to create. The options are `vector-ivf` and `vector-hnsw`. Note `vector-ivf` is available on all cluster tiers and `vector-hnsw` is available on M40 cluster tiers and higher. |
61+
|`m` |integer |The max number of connections per layer (`16` by default, minimum value is `2`, maximum value is `100`). Higher m is suitable for datasets with high dimensionality and/or high accuracy requirements. |
62+
|`efConstruction` |integer |the size of the dynamic candidate list for constructing the graph (`64` by default, minimum value is `4`, maximum value is `1000`). Higher `efConstruction` will result in better index quality and higher accuracy, but it will also increase the time required to build the index. `efConstruction` has to be at least `2 * m` |
63+
|`similarity` |string |Similarity metric to use with the index. Possible options are `COS` (cosine distance), `L2` (Euclidean distance), and `IP` (inner product). |
64+
|`dimensions` |integer |Number of dimensions for vector similarity. The maximum number of supported dimensions is `2000`. |
65+
66+
### Perform a vector search with HNSW
67+
To perform a vector search, use the `$search` aggregation pipeline stage the query with the `cosmosSearch` operator.
68+
```javascript
69+
{
70+
"$search": {
71+
"cosmosSearch": {
72+
"vector": <query_vector>,
73+
"path": "<path_to_property>",
74+
"k": <num_results_to_return>,
75+
"efSearch": <integer_value>
76+
},
77+
}
78+
}
79+
}
80+
81+
```
82+
|Field |Type |Description |
83+
|---------|---------|---------|
84+
|`efSearch` |integer |The size of the dynamic candidate list for search (`40` by default). A higher value provides better recall at the cost of speed. |
85+
|`k` |integer |The number of results to return. it should be less than or equal to `efSearch` |
86+
87+
> [!NOTE]
88+
> Creating an HSNW index with large datasets can result in your Azure Cosmos DB for MongoDB vCore resource running out of memory, or can limit the performance of other operations running on your database. If you encounter such issues, these can be mitigated by scaling your resource to a higher cluster tier, or reducing the size of the dataset.
89+
90+
### Create an vector index using IVF
91+
92+
To create a vector index using the IVF (Inverted File) algorithm, use the following `createIndexes` template and set the `"kind"` paramter to `"vector-ivf"`:
3193

3294
```json
3395
{
@@ -53,9 +115,9 @@ To create a vector index, use the following `createIndexes` template:
53115
| --- | --- | --- |
54116
| `index_name` | string | Unique name of the index. |
55117
| `path_to_property` | string | Path to the property that contains the vector. This path can be a top-level property or a dot notation path to the property. If a dot notation path is used, then all the nonleaf elements can't be arrays. Vectors must be a `number[]` to be indexed and return in vector search results.|
56-
| `kind` | string | Type of vector index to create. Primarily, `vector-ivf` is supported. `vector-hnsw` is available as a preview feature that requires enablement via [Azure Feature Enablement Control](../../../azure-resource-manager/management/preview-features.md).|
118+
| `kind` | string | Type of vector index to create. The options are `vector-ivf` and `vector-hnsw`. Note `vector-ivf` is available on all cluster tiers and `vector-hnsw` is available on M40 cluster tiers and higher. |
57119
| `numLists` | integer | This integer is the number of clusters that the inverted file (IVF) index uses to group the vector data. We recommend that `numLists` is set to `documentCount/1000` for up to 1 million documents and to `sqrt(documentCount)` for more than 1 million documents. Using a `numLists` value of `1` is akin to performing brute-force search, which has limited performance. |
58-
| `similarity` | string | Similarity metric to use with the IVF index. Possible options are `COS` (cosine distance), `L2` (Euclidean distance), and `IP` (inner product). |
120+
| `similarity` | string | Similarity metric to use with the index. Possible options are `COS` (cosine distance), `L2` (Euclidean distance), and `IP` (inner product). |
59121
| `dimensions` | integer | Number of dimensions for vector similarity. The maximum number of supported dimensions is `2000`. |
60122

61123
> [!IMPORTANT]
@@ -65,10 +127,153 @@ To create a vector index, use the following `createIndexes` template:
65127
>
66128
> If you're experimenting with a new scenario or creating a small demo, you can start with `numLists` set to `1` to perform a brute-force search across all vectors. This should provide you with the most accurate results from the vector search, however be aware that the search speed and latency will be slow. After your initial setup, you should go ahead and tune the `numLists` parameter using the above guidance.
67129
130+
### Perform a vector search with IVF
131+
132+
To perform a vector search, use the `$search` aggregation pipeline stage in a MongoDB query. To use the `cosmosSearch` index, use the new `cosmosSearch` operator.
133+
134+
```json
135+
{
136+
{
137+
"$search": {
138+
"cosmosSearch": {
139+
"vector": <query_vector>,
140+
"path": "<path_to_property>",
141+
"k": <num_results_to_return>,
142+
},
143+
"returnStoredSource": True }},
144+
{
145+
"$project": { "<custom_name_for_similarity_score>": {
146+
"$meta": "searchScore" },
147+
"document" : "$$ROOT"
148+
}
149+
}
150+
}
151+
```
152+
To retrieve the similarity score (`searchScore`) along with the documents found by the vector search, use the `$project` operator to include `searchScore` and rename it as `<custom_name_for_similarity_score>` in the results. Then the document is also projected as nested object. Note that the similarity score is calculated using the metric defined in the vector index.
153+
154+
68155
> [!IMPORTANT]
69156
> Vectors must be a `number[]` to be indexed. Using another type, such as `double[]`, prevents the document from being indexed. Non-indexed documents won't be returned in the result of a vector search.
70157
71-
## Examples
158+
## Example using an HNSW index.
159+
160+
The following examples show you how to index vectors, add documents that have vector properties, perform a vector search, and retrieve the index configuration.
161+
162+
```javascript
163+
use test;
164+
165+
db.createCollection("exampleCollection");
166+
167+
db.runCommand({
168+
"createIndexes": "exampleCollection",
169+
"indexes": [
170+
{
171+
"name": "VectorSearchIndex",
172+
"key": {
173+
"contentVector": "cosmosSearch"
174+
},
175+
"cosmosSearchOptions": {
176+
"kind": "vector-hnsw",
177+
"m": 16,
178+
"efConstruction": 64,
179+
"similarity": "COS",
180+
"dimensions": 3
181+
}
182+
}
183+
]
184+
});
185+
```
186+
This command creates an HNSW index against the `contentVector` property in the documents that are stored in the specified collection, `exampleCollection`. The `cosmosSearchOptions` property specifies the parameters for the HNSW vector index. If your document has the vector stored in a nested property, you can set this property by using a dot notation path. For example, you might use `text.contentVector` if `contentVector` is a subproperty of `text`.
187+
188+
### Add vectors to your database
189+
190+
To add vectors to your database's collection, you first need to create the [embeddings](../../../ai-services/openai/concepts/understand-embeddings.md) by using your own model, [Azure OpenAI Embeddings](../../../cognitive-services/openai/tutorials/embeddings.md), or another API (such as [Hugging Face on Azure](https://azure.microsoft.com/solutions/hugging-face-on-azure/)). In this example, new documents are added through sample embeddings:
191+
192+
```javascript
193+
db.exampleCollection.insertMany([
194+
{name: "Eugenia Lopez", bio: "Eugenia is the CEO of AdvenureWorks.", vectorContent: [0.51, 0.12, 0.23]},
195+
{name: "Cameron Baker", bio: "Cameron Baker CFO of AdvenureWorks.", vectorContent: [0.55, 0.89, 0.44]},
196+
{name: "Jessie Irwin", bio: "Jessie Irwin is the former CEO of AdventureWorks and now the director of the Our Planet initiative.", vectorContent: [0.13, 0.92, 0.85]},
197+
{name: "Rory Nguyen", bio: "Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.", vectorContent: [0.91, 0.76, 0.83]},
198+
]);
199+
```
200+
201+
### Perform a vector search
202+
203+
Continuing with the last example, create another vector, `queryVector`. Vector search measures the distance between `queryVector` and the vectors in the `contentVector` path of your documents. You can set the number of results that the search returns by setting the parameter `k`, which is set to `2` here. You can also set `efSearch`, which is an integer that controls the size of the candidate vector list. A higher value may improve accuracy, however the search will be slower as a result. This is an optional parameter with a default value of 40.
204+
205+
```javascript
206+
const queryVector = [0.52, 0.28, 0.12];
207+
db.exampleCollection.aggregate([
208+
{
209+
"$search": {
210+
"cosmosSearch": {
211+
"vector": "queryVector",
212+
"path": "contentVector",
213+
"k": 2,
214+
"efSearch": 40
215+
},
216+
}
217+
}
218+
}
219+
]);
220+
```
221+
222+
In this example, a vector search is performed by using `queryVector` as an input via the Mongo shell. The search result is a list of two items that are most similar to the query vector, sorted by their similarity scores.
223+
224+
```javascript
225+
[
226+
{
227+
similarityScore: 0.9465376,
228+
document: {
229+
_id: ObjectId("645acb54413be5502badff94"),
230+
name: 'Eugenia Lopez',
231+
bio: 'Eugenia is the CEO of AdvenureWorks.',
232+
vectorContent: [ 0.51, 0.12, 0.23 ]
233+
}
234+
},
235+
{
236+
similarityScore: 0.9006955,
237+
document: {
238+
_id: ObjectId("645acb54413be5502badff97"),
239+
name: 'Rory Nguyen',
240+
bio: 'Rory Nguyen is the founder of AdventureWorks and the president of the Our Planet initiative.',
241+
vectorContent: [ 0.91, 0.76, 0.83 ]
242+
}
243+
}
244+
]
245+
```
246+
247+
### Get vector index definitions
248+
249+
To retrieve your vector index definition from the collection, use the `listIndexes` command:
250+
251+
``` javascript
252+
db.exampleCollection.getIndexes();
253+
```
254+
255+
In this example, `vectorIndex` is returned with all the `cosmosSearch` parameters that were used to create the index:
256+
257+
```javascript
258+
[
259+
{ v: 2, key: { _id: 1 }, name: '_id_', ns: 'test.exampleCollection' },
260+
{
261+
v: 2,
262+
key: { contentVector: 'cosmosSearch' },
263+
name: 'vectorSearchIndex',
264+
cosmosSearch: {
265+
kind: 'vector-hnsw',
266+
m: 40,
267+
efConstruction: 64
268+
similarity: 'COS',
269+
dimensions: 3
270+
},
271+
ns: 'test.exampleCollection'
272+
}
273+
]
274+
```
275+
276+
## Example using an IVF Index
72277

73278
The following examples show you how to index vectors, add documents that have vector properties, perform a vector search, and retrieve the index configuration.
74279

@@ -215,74 +420,57 @@ In this example, `vectorIndex` is returned with all the `cosmosSearch` parameter
215420
]
216421
```
217422

218-
## HNSW vector index (preview)
423+
## Filtered vector search (preview)
424+
You can now execute vector searches with any supported query filter such as `$lt, $lte, $eq, $neq, $gte, $gt, $in, $nin, and $regex`. Enable the "filtering vector search" feature in the "Preview Features" tab of your Azure Subscription. Learn more about preview features [here](../../../azure-resource-manager/management/preview-features.md).
219425

220-
HNSW stands for Hierarchical Navigable Small World, a graph-based data structure that partitions vectors into clusters and subclusters. With HNSW, you can perform fast approximate nearest neighbor search at higher speeds with greater accuracy.
426+
First, you'll need to define an index for your filter in addition to a vector index. For example, you can define the filter index on a property
221427

222-
As a preview feature, this must be enabled using Azure Feature Enablement Control (AFEC) by selecting the "mongoHnswIndex" feature. For more information, see [enable preview features](../../../azure-resource-manager/management/preview-features.md).
223-
224-
### Create an HNSW vector index
428+
```javascript
429+
db.runCommand({
430+
"createIndexes": "<collection_name",
431+
"indexes": [ {
432+
"key": {
433+
"<property_to_filter>": 1
434+
},
435+
"name": "<name_of_filter_index>"
436+
}
437+
]
438+
});
439+
```
225440

226-
To use HNSW as your index algorithm, you need to create a vector index with the `kind` parameter set to "vector-hnsw" following the template below:
441+
Next, you can add the `"filter"` term to your vector search as shown below. In this example the filter is looking for documents where the `"title"` property is not in the list of `["not in this text", "or this text"]`.
227442

228443
```javascript
229-
{
230-
"createIndexes": "<collection_name>",
231-
"indexes": [
232-
{
233-
"name": "<index_name>",
234-
"key": {
235-
"<path_to_property>": "cosmosSearch"
236-
},
237-
"cosmosSearchOptions": {
238-
"kind": "vector-hnsw",
239-
"m": <integer_value>,
240-
"efConstruction": <integer_value>,
241-
"similarity": "<string_value>",
242-
"dimensions": <integer_value>
243-
}
244-
}
245-
]
444+
445+
db.exampleCollection.aggregate([
446+
{
447+
'$search': {
448+
"cosmosSearch": {
449+
"vector": "<query_vector>",
450+
"path": <path_to_vector>,
451+
"k": num_results,
452+
"filter": {<property_to_filter>: {"$nin": ["not in this text", "or this text"]}}
453+
},
454+
"returnStoredSource": True }},
455+
{'$project': { 'similarityScore': { '$meta': 'searchScore' }, 'document' : '$$ROOT' }
246456
}
457+
]);
247458
```
459+
> [!IMPORTANT]
460+
> While in preview, filtered vector search may require you to adjust your vector index parameters to achieve higher accuracy. For example, increasing `m`, `efConstruction`, or `efSearch` when using HNSW, or `numLists`, or `nProbes` when using IVF, may lead to better results. You should test your configuration before use to ensure that the results are satisfactory.
248461
249-
|Field |Type |Description |
250-
|---------|---------|---------|
251-
| `kind` | string | Type of vector index to create. Type of vector index to create. Primarily, `vector-ivf` is supported. `vector-hnsw` is available as a preview feature that requires enablement via [Azure Feature Enablement Control](../../../azure-resource-manager/management/preview-features.md).|
252-
|`m` |integer |The max number of connections per layer (`16` by default, minimum value is `2`, maximum value is `100`). Higher m is suitable for datasets with high dimensionality and/or high accuracy requirements. |
253-
|`efConstruction` |integer |the size of the dynamic candidate list for constructing the graph (`64` by default, minimum value is `4`, maximum value is `1000`). Higher `efConstruction` will result in better index quality and higher accuracy, but it will also increase the time required to build the index. `efConstruction` has to be at least `2 * m` |
254-
|`similarity` |string |Similarity metric to use with the index. Possible options are `COS` (cosine distance), `L2` (Euclidean distance), and `IP` (inner product). |
255-
|`dimensions` |integer |Number of dimensions for vector similarity. The maximum number of supported dimensions is `2000`. |
256-
462+
## Use LLM Orchestration tools
257463

258-
> [!WARNING]
259-
> Using the HSNW vector index (preview) with large datasets can result in resource running out of memory, or reducing the performance of other operations running on your database. To reduce the chance of this happening, we recommend to:
260-
> - Only use HNSW indexes on a cluster tier of M40 or higher.
261-
> - Scale to a higher cluster tier or reduce the size of the database if your encounter errors.
464+
### Use as a vector database with Semantic Kernel
465+
Use Semantic Kernel to orchestrate your information retrieval from Azure Cosmos DB for MongoDB vCore and your LLM. Learn more [here](https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/memory/azure_cosmosdb).
262466

263-
### Perform a vector search with HNSW
264-
To perform a vector search, use the `$search` aggregation pipeline stage the query with the `cosmosSearch` operator.
265-
```javascript
266-
{
267-
"$search": {
268-
"cosmosSearch": {
269-
"vector": <vector_to_search>,
270-
"path": "<path_to_property>",
271-
"k": <num_results_to_return>,
272-
"efSearch": <integer_value>
273-
},
274-
}
275-
}
276-
}
467+
https://github.com/microsoft/semantic-kernel/tree/main/python/semantic_kernel/connectors/memory/azure_cosmosdb
277468

278-
```
279-
|Field |Type |Description |
280-
|---------|---------|---------|
281-
|`efSearch` |integer |The size of the dynamic candidate list for search (`40` by default). A higher value provides better recall at the cost of speed. |
282-
|`k` |integer |The number of results to return. it should be less than or equal to `efSearch` |
469+
### Use as a vector database with LangChain
470+
Use LangChain to orchestrate your information retrieval from Azure Cosmos DB for MongoDB vCore and your LLM. Learn more [here](https://python.langchain.com/docs/integrations/vectorstores/azure_cosmos_db).
283471

284-
## Use as a vector database with LangChain
285-
You can now use LangChain to orchestrate your information retrieval from Azure Cosmos DB for MongoDB vCore and your LLM. Learn more [here](https://python.langchain.com/docs/integrations/vectorstores/azure_cosmos_db).
472+
### Use as a semantic cache with LangChain
473+
Use LangChain and Azure Cosmos DB for MongoDB (vCore) to orchestrate Semantic Caching, using previously recocrded LLM respones that can save you LLM API costs and reduce latency for responses. Learn more [here](https://python.langchain.com/docs/integrations/llms/llm_caching#azure-cosmos-db-semantic-cache)
286474

287475
## Features and limitations
288476

0 commit comments

Comments
 (0)