{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "683953b3",
   "metadata": {},
   "source": [
    "# MongoDB Atlas\n",
    "\n",
    ">[MongoDB Atlas](https://www.mongodb.com/docs/atlas/) is a fully-managed cloud database available in AWS , Azure, and GCP.  It now has support for native Vector Search on your MongoDB document data.\n",
    "\n",
    "This notebook shows how to use `MongoDB Atlas Vector Search` to store your embeddings in MongoDB documents, create a vector search index, and perform KNN search with an approximate nearest neighbor algorithm.\n",
    "\n",
    "It uses the [knnBeta Operator](https://www.mongodb.com/docs/atlas/atlas-search/knn-beta) available in MongoDB Atlas Search. This feature is in Public Preview and available for evaluation purposes, to validate functionality, and to gather feedback from public preview users. It is not recommended for production deployments as we may introduce breaking changes.\n",
    "\n",
    "To use MongoDB Atlas, you must first deploy a cluster. We have a Forever-Free tier of clusters available. \n",
    "To get started head over to Atlas here: [quick start](https://www.mongodb.com/docs/atlas/getting-started/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4c41cad-08ef-4f72-a545-2151e4598efe",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "!pip install pymongo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1e38361-c1fe-4ac6-86e9-c90ebaf7ae87",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import getpass\n",
    "\n",
    "MONGODB_ATLAS_CLUSTER_URI = getpass.getpass(\"MongoDB Atlas Cluster URI:\")\n",
    "MONGODB_ATLAS_CLUSTER_URI = os.environ[\"MONGODB_ATLAS_CLUSTER_URI\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "457ace44-1d95-4001-9dd5-78811ab208ad",
   "metadata": {},
   "source": [
    "We want to use `OpenAIEmbeddings` so we need to set up our OpenAI API Key. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2d8f240d",
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"OpenAI API Key:\")\n",
    "OPENAI_API_KEY = os.environ[\"OPENAI_API_KEY\"]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "1f3ecc42",
   "metadata": {},
   "source": [
    "Now, let's create a vector search index on your cluster. In the below example, `embedding` is the name of the field that contains the embedding vector. Please refer to the [documentation](https://www.mongodb.com/docs/atlas/atlas-search/define-field-mappings-for-vector-search) to get more details on how to define an Atlas Vector Search index.\n",
    "You can name the index `langchain_demo` and create the index on the namespace `lanchain_db.langchain_col`. Finally, write the following definition in the JSON editor on MongoDB Atlas:\n",
    "\n",
    "```json\n",
    "{\n",
    "  \"mappings\": {\n",
    "    \"dynamic\": true,\n",
    "    \"fields\": {\n",
    "      \"embedding\": {\n",
    "        \"dimensions\": 1536,\n",
    "        \"similarity\": \"cosine\",\n",
    "        \"type\": \"knnVector\"\n",
    "      }\n",
    "    }\n",
    "  }\n",
    "}\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "aac9563e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain.embeddings.openai import OpenAIEmbeddings\n",
    "from langchain.text_splitter import CharacterTextSplitter\n",
    "from langchain.vectorstores import MongoDBAtlasVectorSearch\n",
    "from langchain.document_loaders import TextLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "a3c3999a",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.document_loaders import TextLoader\n",
    "\n",
    "loader = TextLoader(\"../../../state_of_the_union.txt\")\n",
    "documents = loader.load()\n",
    "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n",
    "docs = text_splitter.split_documents(documents)\n",
    "\n",
    "embeddings = OpenAIEmbeddings()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e104aee",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymongo import MongoClient\n",
    "\n",
    "# initialize MongoDB python client\n",
    "client = MongoClient(MONGODB_ATLAS_CLUSTER_URI)\n",
    "\n",
    "db_name = \"langchain_db\"\n",
    "collection_name = \"langchain_col\"\n",
    "collection = client[db_name][collection_name]\n",
    "index_name = \"langchain_demo\"\n",
    "\n",
    "# insert the documents in MongoDB Atlas with their embedding\n",
    "docsearch = MongoDBAtlasVectorSearch.from_documents(\n",
    "    docs, embeddings, collection=collection, index_name=index_name\n",
    ")\n",
    "\n",
    "# perform a similarity search between the embedding of the query and the embeddings of the documents\n",
    "query = \"What did the president say about Ketanji Brown Jackson\"\n",
    "docs = docsearch.similarity_search(query)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c608226",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(docs[0].page_content)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "851a2ec9-9390-49a4-8412-3e132c9f789d",
   "metadata": {},
   "source": [
    "You can reuse the vector search index you created, make sure the `OPENAI_API_KEY` environment variable is set up, then execute another query."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6336fe79-3e73-48be-b20a-0ff1bb6a4399",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymongo import MongoClient\n",
    "from langchain.vectorstores import MongoDBAtlasVectorSearch\n",
    "from langchain.embeddings.openai import OpenAIEmbeddings\n",
    "import os\n",
    "\n",
    "MONGODB_ATLAS_URI = os.environ[\"MONGODB_ATLAS_URI\"]\n",
    "\n",
    "# initialize MongoDB python client\n",
    "client = MongoClient(MONGODB_ATLAS_URI)\n",
    "\n",
    "db_name = \"langchain_db\"\n",
    "collection_name = \"langchain_col\"\n",
    "collection = client[db_name][collection_name]\n",
    "index_name = \"langchain_demo\"\n",
    "\n",
    "# initialize vector store\n",
    "vectorStore = MongoDBAtlasVectorSearch(\n",
    "    collection, OpenAIEmbeddings(), index_name=index_name\n",
    ")\n",
    "\n",
    "# perform a similarity search between a query and the ingested documents\n",
    "query = \"What did the president say about Ketanji Brown Jackson\"\n",
    "docs = vectorStore.similarity_search(query)\n",
    "\n",
    "print(docs[0].page_content)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
