Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions source/fundamentals/indexes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,91 @@ field in the ``sample_mflix.movies`` collection:

Name of Index Created: cast_-1

.. _golang-atlas-search-indexes:

Atlas Search and Vector Search Indexes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can programmatically manage your MongoDB Atlas Search and Atlas Vector
Search indexes by using the {+driver-short+}.

The Atlas Search feature enables you to perform full-text searches on
collections hosted on MongoDB Atlas. To learn more about Atlas
Search, see the :atlas:`Atlas Search
</atlas-search/atlas-search-overview/>` documentation.

Atlas Vector Search enables you to perform semantic searches on vector
embeddings stored in Atlas. To learn more about Atlas
Vector Search, see the :atlas:`Atlas Vector Search
</atlas-vector-search/vector-search-overview/>` documentation.

.. Add when Go AVS guide is ready:
.. To learn more about Atlas Vector Search, see the :ref:`golang-atlas-vector-search` guide.

The following sections contain code examples that demonstrate how to manage Atlas
Search indexes.

Create a Search Index
`````````````````````

You can create an Atlas Vector Search index or an Atlas Search index by providing
an index definition to the ``createOne()`` method.

The following example creates an Atlas Vector Search index on the ``plot_embedding``
field in the ``sample_mflix.embedded_movies`` collection:

.. literalinclude:: /includes/fundamentals/code-snippets/indexes/atlasVectorSearch.go
:language: go
:start-after: start-create-vector-search
:end-before: end-create-vector-search
:dedent:

The following example creates an Atlas Search index on the ``plot`` field of the
``sample_mflix.movies`` collection:

.. literalinclude:: /includes/fundamentals/code-snippets/indexes/atlasVectorSearch.go
:language: go
:start-after: start-create-atlas-search
:end-before: end-create-atlas-search
:dedent:

List a Search Index
```````````````````

The following example lists the details of the specified search index:

.. literalinclude:: /includes/fundamentals/code-snippets/indexes/atlasVectorSearch.go
:language: go
:start-after: start-list-index
:end-before: end-list-index
:dedent:

Update Search Indexes
`````````````````````

You can update an Atlas Search or Atlas Vector Search index by specifying the name of the index
and the new index definition.

The following example updates an Atlas Vector Search index by providing the name of the index and
a new index definition:

.. literalinclude:: /includes/fundamentals/code-snippets/indexes/atlasVectorSearch.go
:language: go
:start-after: start-update-index
:end-before: end-update-index
:dedent:

Delete Search Indexes
`````````````````````

The following example deletes an Atlas Search index with the specified name:

.. literalinclude:: /includes/fundamentals/code-snippets/indexes/atlasVectorSearch.go
:language: go
:start-after: start-delete-index
:end-before: end-delete-index
:dedent:

.. _golang-clustered-indexes:

Clustered Indexes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package main

import (
"context"
"fmt"
"log"
"time"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)

func main() {
ctx := context.Background()

// Retrieves your Atlas connection string
uri := os.Getenv("MONGODB_ATLAS_URI")
if uri == "" {
log.Fatal("MONGODB_ATLAS_URI environment variable is not set")
}

// Connect to your Atlas cluster
clientOptions := options.Client().ApplyURI(uri)
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatalf("Failed to connect to the server: %v", err)
}
defer func() {
if err := client.Disconnect(ctx); err != nil {
log.Fatalf("Failed to disconnect: %v", err)
}
}()

// Set the namespace
coll := client.Database("sample_mflix").Collection("embedded_movies")

// start-create-vector-search
// Defines the structs used for the index definition
type vectorDefinitionField struct {
Type string `bson:"type"`
Path string `bson:"path"`
NumDimensions int `bson:"numDimensions"`
Similarity string `bson:"similarity"`
Quantization string `bson:"quantization"`
}

type vectorDefinition struct {
Fields []vectorDefinitionField `bson:"fields"`
}

// Sets the index name and type to "vectorSearch"
const indexName = "vector_index"
opts := options.SearchIndexes().SetName(indexName).SetType("vectorSearch")

// Defines the index definition
vectorSearchIndexModel := mongo.SearchIndexModel{
Definition: vectorDefinition{
Fields: []vectorDefinitionField{{
Type: "vector",
Path: "plot_embedding",
NumDimensions: 1536,
Similarity: "dotProduct",
Quantization: "scalar"}},
},
Options: opts,
}

// Creates the index
searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, vectorSearchIndexModel)
if err != nil {
log.Fatalf("Failed to create the vector search index: %v", err)
}
// end-create-vector-search

// Creates an Atlas Search index
// start-create-atlas-search
// Sets the index name and type to "search"
const indexName = "atlas_search_index"
opts := options.SearchIndexes().SetName(indexName).SetType("search")

// Defines the index definition
searchIndexModel := mongo.SearchIndexModel{
Definition: bson.D{
{Key: "mappings", Value: bson.D{
{Key: "dynamic", Value: false},
{Key: "fields", Value: bson.D{
{Key: "plot", Value: bson.D{
{Key: "type", Value: "string"},
}},
}},
}},
},
Options: opts,
}

// Creates the index
searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel)
if err != nil {
log.Fatalf("Failed to create the atlas search index: %v", err)
}
// end-create-atlas-search

// start-list-index
// Specify the index to retrieve
const indexName = "<indexName>"
opts := options.SearchIndexes().SetName(indexName)

// Retrieves the details of the specified index
cursor, err := coll.SearchIndexes().List(ctx, opts)

// Prints the index details to the console as JSON
var results []bson.D
if err := cursor.All(ctx, &results); err != nil {
log.Fatalf("Failed to unmarshal results to bson: %v", err)
}
res, err := json.Marshal(results)
if err != nil {
log.Fatalf("Failed to marshal results to json: %v", err)
}
fmt.Println(res)
// end-list-index

// start-update-index
// Specify the index name and the new index definition
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Specify the index name and the new index definition
// Specifies the index name and the new index definition

Nit: Keeps it in the same tense as the rest of the comments

Copy link
Collaborator Author

@lindseymoore lindseymoore Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shuangela According to this guidance on code comments, comments that indicate that a user needs to take an action should be imperative. For this section, the user needs to replace the index name and definition, so the imperative tense is necessary here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was going to make the same comment as @shuangela and then saw your response @lindseymoore. We can keep the imperative if that's the guidance, but is there a way we can make it even clearer to the user that they should modify the code here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's an example, I propose we just use the same index name as in the previous examples. As part of this, I would change all of the examples to use the same index name consistently:

const indexName = "atlas_vector_search_index"
const indexName = "atlas_search_index"

or:

const indexName = "vector_search_index"
const indexName = "search_index"

And then we would end up with something like this:

// Specifies the index name and the new index definition 
const indexName = "search_index"

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, do some of the examples apply to both AS and AVS?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the delete, list, and update methods are used the same for both AS and AVS. I updated the examples to remove the placeholders and include more general names, like myIndex. The only exception is in the update section where I made the name vector_index, since the definition shown is for a vector index.
Also changed the comments back to "specifies".

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense. Thanks for making the change.

Any reason you decided to not make the names atlas_search_index and vector_index more consistent though? I would either use "atlas" for both or neither. Also, the corresponding terms are "search" vs "vector search" rather than "search" vs "vector". Let me know if there's something I'm missing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying! Updated names to vector_search_index and search_index

const indexName = "<indexName>"

type vectorDefinitionField struct {
Type string `bson:"type"`
Path string `bson:"path"`
NumDimensions int `bson:"numDimensions"`
Similarity string `bson:"similarity"`
}

type vectorDefinition struct {
Fields []vectorDefinitionField `bson:"fields"`
}

definition := vectorDefinition{
Fields: []vectorDefinitionField{{
Type: "vector",
Path: "<fieldToIndex>",
NumDimensions: <numberOfDimensions>,
Similarity: "dotProduct"}},
}

// Updates the specified index
err := coll.SearchIndexes().UpdateOne(ctx, indexName, definition)
if err != nil {
log.Fatalf("Failed to update the index: %v", err)
}
// end-update-index

// start-delete-index
err := coll.SearchIndexes().DropOne(ctx, "<indexName>")
if err != nil {
log.Fatalf("Failed to delete the index: %v", err)
}
// end-delete-index

}
Loading