diff --git a/img/search/add-data.png b/img/search/add-data.png new file mode 100644 index 00000000..0caaa6d9 Binary files /dev/null and b/img/search/add-data.png differ diff --git a/img/search/add-document.png b/img/search/add-document.png new file mode 100644 index 00000000..95d34790 Binary files /dev/null and b/img/search/add-document.png differ diff --git a/img/search/create-database.png b/img/search/create-database.png new file mode 100644 index 00000000..d393813e Binary files /dev/null and b/img/search/create-database.png differ diff --git a/img/search/database-created.png b/img/search/database-created.png new file mode 100644 index 00000000..d1cdbf8f Binary files /dev/null and b/img/search/database-created.png differ diff --git a/img/search/first-search.png b/img/search/first-search.png new file mode 100644 index 00000000..bdeb1c5f Binary files /dev/null and b/img/search/first-search.png differ diff --git a/img/search/select-plan.png b/img/search/select-plan.png new file mode 100644 index 00000000..757e69b5 Binary files /dev/null and b/img/search/select-plan.png differ diff --git a/mint.json b/mint.json index 18737066..60aa79d1 100644 --- a/mint.json +++ b/mint.json @@ -57,6 +57,10 @@ "name": "Workflow", "url": "workflow" }, + { + "name": "Search", + "url": "search" + }, { "name": "Developer API", "url": "devops" @@ -1377,6 +1381,81 @@ "workflow/roadmap", "workflow/llms-txt" ] + }, + { + "group": "", + "pages": [ + { + "group": "Overall", + "pages": [ + "search/overall/getstarted", + "search/overall/whatisupstashsearch", + "search/overall/pricing" + ] + }, + { + "group": "Features", + "pages": [ + "search/features/algorithm", + "search/features/indexes", + "search/features/content-and-metadata", + "search/features/filtering", + "search/features/reranking" + ] + }, + { + "group": "SDKs", + "pages": [ + { + "group": "Typescript", + "pages": [ + "search/sdks/ts/getting-started", + "search/sdks/ts/contributing", + { + "group": "Commands", + "pages": [ + "search/sdks/ts/commands/search", + "search/sdks/ts/commands/upsert", + "search/sdks/ts/commands/fetch", + "search/sdks/ts/commands/delete", + "search/sdks/ts/commands/range", + "search/sdks/ts/commands/reset", + "search/sdks/ts/commands/info" + ] + } + ] + }, + { + "group": "Python", + "pages": [ + "search/sdks/py/gettingstarted", + { + "group": "Commands", + "pages": [ + "search/sdks/py/commands/search", + "search/sdks/py/commands/upsert", + "search/sdks/py/commands/fetch", + "search/sdks/py/commands/delete", + "search/sdks/py/commands/range", + "search/sdks/py/commands/reset", + "search/sdks/py/commands/info" + ] + } + ] + } + ] + }, + { + "group": "Quickstarts", + "pages": [ + "search/tutorials/nextjs" + ] + }, + { + "group": "Help", + "pages": ["search/help/faq"] + } + ] } ], "api": { diff --git a/search/.keep b/search/.keep new file mode 100644 index 00000000..db835f70 --- /dev/null +++ b/search/.keep @@ -0,0 +1 @@ +// This file ensures the search directory is tracked by version control. \ No newline at end of file diff --git a/search/features/algorithm.mdx b/search/features/algorithm.mdx new file mode 100644 index 00000000..949a6085 --- /dev/null +++ b/search/features/algorithm.mdx @@ -0,0 +1,19 @@ +--- +title: Algorithm +--- + +Upstash Search blends semantic search with traditional exact keyword matching +to deliver results that are both accurate and relevant. By combining these +two approaches, it captures what users mean, not just what they type, +while still making sure exact keyword hits aren’t missed. + +The system uses a hybrid setup that supports flexible “OR” logic for full-text search, +which pairs nicely with the semantic side. Together, they let Upstash Search: + +- Understand the intent behind a query, even if the wording isn’t exact +- Find documents with related or alternative phrasing +- Work across all kinds of content and domains + +Behind the scenes, user queries get a subtle boost from large language models, +helping the system better understand context and return smarter results +even when queries are vague or incomplete. diff --git a/search/features/content-and-metadata.mdx b/search/features/content-and-metadata.mdx new file mode 100755 index 00000000..f7d081e8 --- /dev/null +++ b/search/features/content-and-metadata.mdx @@ -0,0 +1,83 @@ +--- +title: Content and Metadata +--- + +## Content + +Content is the indexed component of documents. It is a json +object which is indexed and can also be [filtered](/search/features/filtering). + +It is mandatory to provide the content while upserting documents. + + + + +```py +index.upsert( + documents=[ + { + "id": "star-wars", + "content": { "text": "Star Wars is a sci-fi space opera."} + } + ] +) +``` + + + +```ts +await index.upsert([ + { + id: "star-wars", + content: { title: "Star Wars", genre: "sci-fi", category: "classic" } + } +]); +``` + + + + +## Metadata + +Metadata allow you to attach more context to your documents. +It is an optional JSON structured object, which does not +get indexed with the documents. + +It has two main use cases: + +1. As additional context for your application logic +2. As filtering input for search queries + +You can upsert metadata with your documents as follows: + + + + +```py +index.upsert( + documents=[ + { + "id": "star-wars", + "content": { "text": "Star Wars is a sci-fi space opera."}, + "metadata": { + "genre": "sci-fi", + } + } + ] +) +``` + + + +```ts +await index.upsert([ + { + id: "star-wars", + content: { title: "Star Wars", genre: "sci-fi", category: "classic" }, + metadata: { director: "George Lucas" } , + } +]); +``` + + + diff --git a/search/features/filtering.mdx b/search/features/filtering.mdx new file mode 100644 index 00000000..89fc2054 --- /dev/null +++ b/search/features/filtering.mdx @@ -0,0 +1,314 @@ +--- +title: Filtering with Content +--- + +You can further restrict the search by providing a filter based on a specific content keys. + +Search queries with filters only return documents which have the content matching with the filter. + +Upstash Search allows you to filter by content keys which have the following value types: + +- string +- number +- boolean +- object +- array + +Filtering is implemented as a combination of in and post-filtering. Every query is assigned a filtering budget, +determining the number of candidate documents that can be compared against the filter during query execution. If this +budget is exceeded, the system fallbacks into post-filtering. Therefore, with highly selective filters, fewer +than `topK` documents may be returned. + +## Filter Syntax + +A filter has a syntax that resembles SQL, which consists of operators on content keys and boolean operators +to combine them. + +Assuming you have content like below: + +```json +{ + "city": "Istanbul", + "country": "Turkey", + "is_capital": false, + "population": 15460000, + "geography": { + "continent": "Asia", + "coordinates": { + "latitude": 41.0082, + "longitude": 28.9784 + } + }, + "economy": { + "currency": "TRY", + "major_industries": [ + "Tourism", + "Textiles", + "Finance" + ] + } +} +``` + +Then, you can search similar documents with a filter like below: + + + + +```python +scores = index.search( + query="space opera", + limit=2, + filter="category = 'classic'", +) +``` + + + +```ts +const searchResults = await index.search({ + query: "space", + limit: 2, + filter: "category = 'classic'", +}); +``` + + + + +### Operators + +#### Equals (=) + +The `equals` operator filters content whose values are equal to the given literal. + +It is applicable to _string_, _number_, and _boolean_ values. + +```SQL +country = 'Turkey' AND population = 15460000 AND is_capital = false +``` + +#### Not Equals (!=) + +The `not equals` operator filters content whose values are not equal to the given literal. + +It is applicable to _string_, _number_, and _boolean_ values. + +```SQL +country != 'Germany' AND population != 12500000 AND is_capital != true +``` + +#### Less Than (\<) + +The `less than` operator filters content whose values are less than the given literal. + +It is applicable to _number_ values. + +```SQL +population < 20000000 OR geography.coordinates.longitude < 30.0 +``` + +#### Less Than or Equals (\<=) + +The `less than or equals` operator filters content whose values are less than or equal to the given literal. + +It is applicable to _number_ values. + +```SQL +population <= 20000000 OR geography.coordinates.longitude <= 30.0 +``` + +#### Greater Than (>) + +The `greater than` operator filters content whose values are greater than the given literal. + +It is applicable to _number_ values. + +```SQL +population > 10000000 OR geography.coordinates.latitude > 39.5 +``` + +#### Greater Than or Equals (>=) + +The `greater than or equals` operator filters content whose values are greater than or equal to the given literal. + +It is applicable to _number_ values. + +```SQL +population >= 10000000 OR geography.coordinates.latitude >= 39.5 +``` + +#### Glob + +The `glob` operator filters content whose values match with the given UNIX glob pattern. + +It is applicable to _string_ values. + +It is a case sensitive operator. + +The glob operator supports the following wildcards: + +- `*` matches zero or more characters. +- `?` matches exactly one character. +- `[]` matches one character from the list + - `[abc]` matches either `a`, `b`, or `c`. + - `[a-z]` matches one of the range of characters from `a` to `z`. + - `[^abc]` matches any one character other than `a`, `b`, or `c`. + - `[^a-z]` matches any one character other than `a` to `z`. + +For example, the filter below would only match with city names whose second character is `s` or `z`, +and ends with anything other than `m` to `z`. + +```SQL +city GLOB '?[sz]*[^m-z]' +``` + +#### Not Glob + +The `not glob` operator filters content whose values do not match with the given UNIX glob pattern. + +It is applicable to _string_ values. + +It has the same properties with the glob operator. + +For example, the filter below would only match with city names whose first character is anything other than `A`. + +```SQL +city NOT GLOB 'A*' +``` + +#### In + +The `in` operator filters content whose values are equal to any of the given literals. + +It is applicable to _string_, _number_, and _boolean_ values. + +```SQL +country IN ('Germany', 'Turkey', 'France') +``` + +Semantically, it is equivalent to equals operator applied to all of the given literals with `OR` boolean operator in between: + +```SQL +country = 'Germany' OR country = 'Turkey' OR country = 'France' +``` + +#### Not In + +The `not in` operator filters content whose values are not equal to any of the given literals. + +It is applicable to _string_, _number_, and _boolean_ values. + +```SQL +economy.currency NOT IN ('USD', 'EUR') +``` + +Semantically, it is equivalent to not equals operator applied to all of the given literals with `AND` boolean operator in between: + +```SQL +economy.currency != 'USD' AND economy.currency != 'EUR' +``` + +#### Contains + +The `contains` operator filters content whose values contain the given literal. + +It is applicable to _array_ values. + +```SQL +economy.major_industries CONTAINS 'Tourism' +``` + +#### Not Contains + +The `not contains` operator filters content whose values do not contain the given literal. + +It is applicable to _array_ values. + +```SQL +economy.major_industries NOT CONTAINS 'Steel Production' +``` + +#### Has Field + +The `has field` operator filters content which have the given JSON field. + +```SQL +HAS FIELD geography.coordinates +``` + +#### Has Not Field + +The `has not field` operator filters content which do not have the given JSON field. + + +```SQL +HAS NOT FIELD geography.coordinates.longitude +``` + +### Boolean Operators + +Operators above can be combined with `AND` and `OR` boolean operators to form +compound filters. + +```SQL +country = 'Turkey' AND population > 10000000 +``` + +Boolean operators can be grouped with parentheses to have higher precedence. + +```SQL +country = 'Turkey' AND (population > 10000000 OR is_capital = false) +``` + +When no parentheses are provided in ambiguous filters, `AND` will have higher +precedence than `OR`. So, the filter + +```SQL +country = 'Turkey' AND population > 10000000 OR is_capital = false +``` + +would be equivalent to + +```SQL +(country = 'Turkey' AND population > 10000000) OR is_capital = false +``` + +### Filtering Nested Objects + +It is possible to filter nested object fields by referencing them with the `.` accessor. + +Nested fields can be at arbitrary depths, so more than one `.` accessor can be used +in the same identifier. + +```SQL +economy.currency != 'USD' AND geography.coordinates.latitude >= 35.0 +``` + +### Filtering Array Elements + +Apart from the `CONTAINS` and `NOT CONTAINS` operators, individual array elements can also +be filtered by referencing them with the `[]` accessor by their indexes. + +Indexing is zero based. + +```SQL +economy.major_industries[0] = 'Tourism' +``` + +Also, it is possible to index from the back using the `#` character with negative values. +`#` can be thought as the number of elements in the array, so `[#-1]` would reference the +last element. + +```SQL +economy.major_industries[#-1] = 'Finance' +``` + +### Miscellaneous + +- Identifiers (the left side of the operators) should be of the form `[a-zA-Z_][a-zA-Z_0-9.[\]#-]*`. In simpler terms, they should +start with characters from the English alphabet or `_`, and can continue with same characters plus numbers and other accessors +like `.`, `[0]`, or `[#-1]`. +- The string literals (strings in the right side of the operators) can be either single or double quoted. +- Boolean literals are represented as `1` or `0`. +- The operators, boolean operators, and boolean literals are case insensitive. diff --git a/search/features/indexes.mdx b/search/features/indexes.mdx new file mode 100644 index 00000000..43a6a7d9 --- /dev/null +++ b/search/features/indexes.mdx @@ -0,0 +1,73 @@ +--- +title: Indexes +--- + +Upstash Search allows you to partition a single database into multiple isolated indexes. +Each index acts as a self-contained subset of the database, +search and upsert requests are limited to one index. + +## Using an Index + +Indexes are created implicitly when an upsert operation is performed, +so there is no specific endpoint for creating an index. + +For example, the code snippet below will create the index `foo` if it does not already exist, +upsert and search the document only on that index. + + + + +```python +index = client.index("foo") +index.upsert( ... ) +``` + + + +```ts +const index = client.index("movies"); +await index.upsert( ... ); +``` + + + + +## Listing Indexes + +Names of all the active indexes of a database can be listed as follows: + + + + +```python +client.list_indexes() +``` + + + +```ts +await client.listIndexes() +``` + + + + +## Deleting an Index + +Leftover indexes can be deleted as follows: + + + + +```python +client.delete_index("foo") +``` + + + +```ts +await client.index("foo").deleteIndex(); +``` + + + diff --git a/search/features/reranking.mdx b/search/features/reranking.mdx new file mode 100644 index 00000000..f369b8fa --- /dev/null +++ b/search/features/reranking.mdx @@ -0,0 +1,34 @@ +--- +title: Reranking +--- + +Upstash Search combines semantic and full text search results +seamlessly by default. However, the returned documents can be +reranked using a state of the art model to further improve +the ordering and scoring among them. + +You can opt-in to use reranking for the resulting documents as follows: + + + + +```python +scores = index.search( + query="space opera", + limit=2, + reranking=True, +) +``` + + + +```ts +const searchResults = await index.search({ + query: "space opera", + limit: 2, + reranking: true, +}); +``` + + + diff --git a/search/help/faq.mdx b/search/help/faq.mdx new file mode 100644 index 00000000..f9c62199 --- /dev/null +++ b/search/help/faq.mdx @@ -0,0 +1 @@ +// Placeholder for faq.mdx in search tab \ No newline at end of file diff --git a/search/overall/getstarted.mdx b/search/overall/getstarted.mdx new file mode 100644 index 00000000..f38710ea --- /dev/null +++ b/search/overall/getstarted.mdx @@ -0,0 +1,169 @@ +--- +title: Getting Started +--- + +## Create a Database + +Create a Search Database by navigating to the `Search` tab and clicking on the `Create Database` button. + + + + + +A dialog with the following options will open: + +- **Name:** Type a name for your database (e.g. "product-search"). + +- **Region:** Choose the region for your database. For best performance, select the region closest to your application. + + _We plan to support additional regions and cloud providers. Feel free to send your requests to [support@upstash.com](mailto:support@upstash.com)._ + +Once you're done, click `Next`, choose a plan, and your Database is ready: + + + + + +--- + +## Adding Documents + +Add documents to your database using our REST API, our SDKs, or directly in the dashboard. + +### 1. Adding Documents via Dashboard + +Navigate to the `Data Browser` section of your Database and click `Upsert Documents`: + + + + + +A dialog with the following options will open: + + + + + +- **Index:** An [index](/search/features/indexes) to group your data. + + _If you plan to query all documents in one place, you only need one index (e.g. "product-search"). If you plan to add multi-tenancy, so that each user can only search their own data, for example, you can create one index per user ("user-1", "user-2", etc.)._ + +- **ID:** An automatically generated ID. + +- **Content:** The searchable data in JSON format. + +- **Metadata:** Optional information attached to this document. + +More information about content and metadata can be found [here](/search/features/content-and-metadata). + +--- + +### 2. Adding Documents via SDKs + + + + + +```python +from upstash_search import Search + +client = Search( + url="", + token="", +) + +index = client.index("movies") + +index.upsert( + documents=[ + { + "id": "movie-0", + "content": { + "title": "Star Wars", + "overview": "Sci-fi space opera", + "genre": "sci-fi", + "category": "classic", + }, + "metadata": { + "poster": "https://poster.link/starwars.jpg", + }, + }, + ], +) +``` + + + + +```ts +import { Search } from "@upstash/search"; + +const client = new Search({ + url: "", + token: "", +}); + +const index = client.index("movies"); + +await index.upsert([ + { + id: "star-wars", + content: { title: "Star Wars", genre: "sci-fi", category: "classic" }, + metadata: { director: "George Lucas" } , + }, +]); +``` + + + + +--- + +## Search Your Database + +You can search across your Database the same way: using our REST API, our SDKs or directly in your dashboard. + +### 1. Searching via Dashboard + +To search your documents, enter a search term and click `Search`: + + + + + +### 2. Searching Data via SDKs + + + + +```py +scores = index.search( + query="space opera", + limit=2, +) +``` + + + +```ts +const searchResults = await index.search({ + query: "space opera", + limit: 2, + reranking: true, +}); +``` + + + + +--- + +**That's it!** 🎉 You've just created your first serverless search database with Upstash Search! + +But this is just the beginning. Upstash Search also supports: + +- Advanced reranking +- Fine-grained control over search results +- Metadata-based filtering + +We'll get into those features in the next sections of this documentation. For now, you've already mastered the basics! diff --git a/search/overall/pricing.mdx b/search/overall/pricing.mdx new file mode 100644 index 00000000..95baa4be --- /dev/null +++ b/search/overall/pricing.mdx @@ -0,0 +1,6 @@ +--- +title: Pricing & Limits +url: https://upstash.com/pricing/search +--- + +Please check our [pricing page](https://upstash.com/pricing/search) for the most up-to-date information on pricing and limits. \ No newline at end of file diff --git a/search/overall/whatisupstashsearch.mdx b/search/overall/whatisupstashsearch.mdx new file mode 100644 index 00000000..fcafa574 --- /dev/null +++ b/search/overall/whatisupstashsearch.mdx @@ -0,0 +1,46 @@ +--- +title: What is Upstash Search? +description: Lightweight, AI-powered search for developers +--- + +Upstash Search is a **simple, lightweight, and scalable way to add AI-powered search to your app**. + +We combine full-text and semantic search for highly relevant results. Search works out of the box and scales to massive data sizes with zero infrastructure to manage. + +--- + +## Lightweight & Efficient + +Most search products (we'll avoid names here 💀) are bloated, complicated, and hard to manage. We're building Upstash search to be the exact opposite: fast to set up, easy to use and optimized for real-world use cases. + +- Set up in minutes +- Plug-and-play AI search with smart defaults +- Optimized for speed and simplicity + +--- + +## Fast, Relevant Results + +We have a deep understanding of LLM technology through [Upstash Vector](https://upstash.com/docs/vector/overall/whatisvector) and hosting our own models at scale. We're now using that experience to make search feel truly intelligent. While most search products add AI to catch up, we're making it a core part of Upstash Search from the start. + +- Combines semantic & full-text search for relevancy +- Understands user search intent +- Smart ranking shows the best matches first + +--- + +## Scales Automatically + +We've scaled [Upstash Redis](https://upstash.com/docs/redis/overall/getstarted) to serve billions of requests each day with extremely high availability. That same experience is built into Search, so you never have to think about infra. + +We're building Search for modern, serverless stacks from the ground up. It's ready for any data size you throw at it. + +- Perfect for serverless apps and modern frameworks like Next.js +- Scales to any data size (seriously, we've indexed the entire Wikipedia in 7 languages) +- No infrastructure, clusters or servers to manage + +--- + +## Start using Upstash Search + +Whether you're building a side project or scaling your company, Upstash Search gives you fast, smart, production-ready search with zero infra to manage. Try it today, it only takes a few minutes to [get started](/search/overall/getstarted.mdx)! \ No newline at end of file diff --git a/search/quickstarts/nextjs.ts b/search/quickstarts/nextjs.ts new file mode 100644 index 00000000..e69de29b diff --git a/search/sdks/py/commands/delete.mdx b/search/sdks/py/commands/delete.mdx new file mode 100644 index 00000000..cb073bd5 --- /dev/null +++ b/search/sdks/py/commands/delete.mdx @@ -0,0 +1,49 @@ +--- +title: Delete +--- + +## Delete Command for Python SDK + +The delete method allows you to delete documents from your index using various criteria. + +### Arguments + + + + + One or more document IDs to delete. + + + A string prefix to match document IDs for deletion. All documents with IDs starting with this prefix will be deleted. + + + A metadata filter to use for document deletion. + + Deleting document with filter is a O(N) operation that performs a full + scan. Therefore, it might be slow for large indexes. + + + + + +### Response + + + The number of documents that were successfully deleted. + + + + +```typescript Delete by IDs Array +index.delete(ids=["star-wars", "inception"]); +``` + +```typescript Delete by Prefix +index.delete(prefix="star-"); +``` + +```typescript Delete with Filter +index.delete(filter="age > 30"); +``` + + diff --git a/search/sdks/py/commands/fetch.mdx b/search/sdks/py/commands/fetch.mdx new file mode 100644 index 00000000..82c0bf70 --- /dev/null +++ b/search/sdks/py/commands/fetch.mdx @@ -0,0 +1,51 @@ +--- +title: Fetch +--- + +## Fetch Command for Python SDK + +Used to retrieve documents by their IDs. + +### Arguments + + + + + The IDs of the documents you want to fetch. + + + An ID prefix to match document IDs. + + + + +### Response + + + This field is `null` if no document with the specified ID is found. + + + The ID of the resulting document. + + + The main content of the document. + + + Additional metadata for the document. + + + + + + +```python By ID +documents = index.fetch(ids=["movie-0", "movie-1"]) +print(documents) +``` + +```python ID Prefix +documents = index.fetch(prefix=["movie-"]) +print(documents) +``` + + diff --git a/search/sdks/py/commands/info.mdx b/search/sdks/py/commands/info.mdx new file mode 100644 index 00000000..d147dc22 --- /dev/null +++ b/search/sdks/py/commands/info.mdx @@ -0,0 +1,38 @@ +--- +title: Info +--- + +## Info Command for Python SDK + +Used to retrieve the stats of an index. + +### Response + + + The total number of documents in the database, that are ready to use. + + + The number of documents in the database, that are still processing and not ready to use. + + + Size of the database in bytes. + + + Doctionary of index names and their information (`document_count` and `pending_document_count`) + + + + +```python +from upstash_search import Search + +client = Search( + url="", + token="", +) + +info = client.info() +print(info) +``` + + diff --git a/search/sdks/py/commands/range.mdx b/search/sdks/py/commands/range.mdx new file mode 100644 index 00000000..cb0f74c1 --- /dev/null +++ b/search/sdks/py/commands/range.mdx @@ -0,0 +1,57 @@ +--- +title: Range +--- + +## Range Command for Python SDK + +The range method is used to retrieve documents in chunks with pagination. + +### Arguments + + + + + The cursor to the last retrieved document. Should be set to `""` in the initial range request. + + + The number of maximum documents wanted in the response of range. (page size) + + + + +### Response + + + + + This field is `null` if no document with the specified ID is found. + + + The ID of the resulting document. + + + The main content of the document. + + + Additional metadata for the document. + + + + + The cursor for the next page of documents. + + + + + +```python +range_documents = index.range(cursor="", limit=1) +print(range_documents.documents) + +range_documents = index.range( + cursor=range_documents.next_cursor, + limit=3 +) +print(range_documents.documents) +``` + diff --git a/search/sdks/py/commands/reset.mdx b/search/sdks/py/commands/reset.mdx new file mode 100644 index 00000000..e275029b --- /dev/null +++ b/search/sdks/py/commands/reset.mdx @@ -0,0 +1,29 @@ +--- +title: Reset +--- + +## Reset Command for Python SDK + +The `reset` method allows you to clear all documents from a particular index. + +### Response + + + `'Success'` if the database is successfully reset. + + + + +```python +from upstash_search import Search + +client = Search( + url="", + token="", +) + +index = client.index("movies") +index.reset() +``` + + diff --git a/search/sdks/py/commands/search.mdx b/search/sdks/py/commands/search.mdx new file mode 100644 index 00000000..bfa37623 --- /dev/null +++ b/search/sdks/py/commands/search.mdx @@ -0,0 +1,75 @@ +--- +title: Search +--- + +## Search Command for Python SDK + +The search method is designed to retrieve the most relevant documents from the database, using AI-powered search capabilities. + +### Arguments + + + + + The search query string. + + + The maximum number of results to return. Defaults to 10. + + + Whether to enable AI-powered reranking of results. Disabled by default. + + + A metadata filter for narrowing down the search results. + + + + +### Response + + + This field is `null` if no document with the specified ID is found. + + + The ID of the resulting document. + + + The main content of the document. + + + Additional metadata for the document. + + + Similarity score of the document + + + + + + +```python Basic Search +results = index.search( + query="space opera", + limit=2 +) +print(results) +``` + +```python Search with Reranking +results = index.search( + query="space opera", + limit=2, + reranking=True +) +print(results) +``` + +```python Search with Filter +results = index.search( + query="space", + limit=2, + filter="category = 'classic'" +) +print(results) +``` + diff --git a/search/sdks/py/commands/upsert.mdx b/search/sdks/py/commands/upsert.mdx new file mode 100644 index 00000000..05e600e2 --- /dev/null +++ b/search/sdks/py/commands/upsert.mdx @@ -0,0 +1,55 @@ +--- +title: Upsert +--- + +## Upsert Command for Python SDK + +Used to add new documents or update an existing document. + +### Arguments + + + + + The unique identifier for the document. + + + The main content of the document. + + + Additional metadata for the document. + + + + + + +```python +from upstash_search import Search + +client = Search( + url="", + token="", +) + +index = client.index("movies") + +index.upsert( + documents=[ + { + "id": "movie-0", + "content": { + "title": "Star Wars", + "overview": "Sci-fi space opera", + "genre": "sci-fi", + "category": "classic", + }, + "metadata": { + "poster": "https://poster.link/starwars.jpg", + }, + }, + ], +) +``` + + diff --git a/search/sdks/py/gettingstarted.mdx b/search/sdks/py/gettingstarted.mdx new file mode 100644 index 00000000..78ad912e --- /dev/null +++ b/search/sdks/py/gettingstarted.mdx @@ -0,0 +1,86 @@ +--- +title: Getting Started +--- + +`upstash-search` is a Python SDK for Upstash AI Search, enabling easier operations on Search Databases. + +Using `upstash-search` you can: + +- Perform AI-powered search queries with or without reranking. +- Upsert documents with metadata to an index. +- Fetch documents by their IDs. +- Delete documents from a database. +- Access database stats. +- Reset everything related to a database. + +You can find the GitHub Repository [here](https://github.com/upstash/search-py). + +## Install + +```bash +pip install upstash-search +``` + +## Usage + +### Initializing the client + +There are two pieces of configuration required to use the Upstash search client: a REST token and REST URL. These values can be passed using environment variables or in code through a configuration object. Find your configuration values in [the console dashboard](https://console.upstash.com/search). + +#### Using environment variables + +The environment variables used to configure the client are the following. You can follow [this guide](/search/overall/getstarted) to retrieve credentials. + +```bash +UPSTASH_SEARCH_REST_URL="your_rest_url" +UPSTASH_SEARCH_REST_TOKEN="your_rest_token" +``` + +When these environment variables are set, the client constructor does not require any additional arguments. + +```python +from upstash_search import Search + +client = Search.from_env() +``` + +#### Using a configuration object + +If you prefer to pass configuration in code, the constructor accepts a config object containing the `url` and `token` values. This +could be useful if your application needs to interact with multiple databases, each with a different configuration. + +```python +from upstash_search import Search + +client = Search( + url="", + token="", +) +``` + +--- + +### Using an Index + +The `Search` client is for operations that are about manipulating the Search database. With it, you can create indexes which is where you can upsert and search documents. + +```python +index = client.index("films") + +index.upsert( + documents=[ + { + "id": "movie-0", + "content": { + "title": "Star Wars", + "overview": "Sci-fi space opera", + "genre": "sci-fi", + "category": "classic", + }, + "metadata": { + "poster": "https://poster.link/starwars.jpg", + }, + }, + ], +) +``` \ No newline at end of file diff --git a/search/sdks/ts/commands/delete.mdx b/search/sdks/ts/commands/delete.mdx new file mode 100644 index 00000000..30208856 --- /dev/null +++ b/search/sdks/ts/commands/delete.mdx @@ -0,0 +1,69 @@ +--- +title: Delete +--- + +The delete method allows you to delete documents from your index using various criteria. You can delete documents by their IDs, by ID prefix or with metadata filter. + +## Arguments + + + One or more document IDs to delete. + + +**OR** + + + + + One or more document IDs to delete. + + + A string prefix to match document IDs for deletion. All documents with IDs starting with this prefix will be deleted. + + + A metadata filter to use for document deletion. + + Deleting document with filter is a O(N) operation that performs a full + scan. Therefore, it might be slow for large indexes. + + + + + +## Response + + + + + The number of documents that were successfully deleted. + + + + + + +```typescript Delete by IDs Array +const response = await index.delete(["star-wars", "inception"]); +// { deleted: 2 } +``` + +```typescript Delete Single ID +const response = await index.delete("star-wars"); +// { deleted: 1 } +``` + +```typescript Delete by Prefix +const response = await index.delete({ + prefix: "star-", +}); +// { deleted: 3 } +``` + +```typescript Delete with Filter +const response = await index.delete({ + filter: "age > 30", +}); +// { deleted: 3 } +``` + + diff --git a/search/sdks/ts/commands/fetch.mdx b/search/sdks/ts/commands/fetch.mdx new file mode 100644 index 00000000..6e9c7977 --- /dev/null +++ b/search/sdks/ts/commands/fetch.mdx @@ -0,0 +1,79 @@ +--- +title: Fetch +--- + +Used to retrieve documents by their IDs. + +## Arguments + + + The IDs of the documents you want to fetch. + + +**OR** + + + + + The IDs of the documents you want to fetch. + + + An ID prefix to match document IDs. + + + + +## Response + + + This field is `null` if no document with the specified ID is found. + + + The ID of the resulting document. + + + + + + + + + + +```typescript Basic +await index.fetch({ ids: ["star-wars", "inception"] }); +/* +[ + { + id: "star-wars", + content: { ... }, + metadata: { ... } + }, + { + id: "inception", + content: { ... }, + metadata: { ... } + } +] +*/ +``` + +```typescript ID prefix +await index.fetch({ prefix: "star-" }); +/* +[ + { + id: "star-wars" + content: { ... }, + metadata: { ... } + }, + { + id: "star-trek", + content: { ... }, + metadata: { ... } + } +] +*/ +``` + + diff --git a/search/sdks/ts/commands/info.mdx b/search/sdks/ts/commands/info.mdx new file mode 100644 index 00000000..5b4859a6 --- /dev/null +++ b/search/sdks/ts/commands/info.mdx @@ -0,0 +1,87 @@ +--- +title: Info +--- + +When it comes to info requests, there are two alternatives. One for index level and one for database level. + +## Index Info + +Used to retrieve the stats of an index. + +### Response + + + The total number of documents in the database, that are ready to use. + + + The number of documents in the database, that are still processing and not ready to use. + + +## Database Info + +Alternatively, you can call `info` on the client itself, which will return information about the whole database: + +### Response + + + The total number of documents in the database, that are ready to use. + + + The number of documents in the database, that is still processing and not ready to + use. + + + The size of the database, in `b`. + + + A map of indexes to their information in the following format + + + The total number of documents in the index, that are ready to use. + + + The number of documents in the index, that is still processing and not ready to + use. + + + + + + +```typescript Index +const client = new Search(); +const index = client.index("movies"); + +const infoResponse = await index.info(); +/* +{ + documentCount: 100, + pendingDocumentCount: 5, +} +*/ +``` + +```typescript Database +const client = new Search(); + +const infoResponse = await client.info(); +/* +{ + diskSize: 456890 + pendingDocumentCount: 12, + documentCount: 120, + indexes: { + "movies": { + documentCount: 100, + pendingDocumentCount: 5 + }, + "actors": { + documentCount: 20, + pendingDocumentCount: 7 + } + } +} +*/ +``` + + diff --git a/search/sdks/ts/commands/range.mdx b/search/sdks/ts/commands/range.mdx new file mode 100644 index 00000000..aa3114ca --- /dev/null +++ b/search/sdks/ts/commands/range.mdx @@ -0,0 +1,73 @@ +--- +title: Range +--- + +The range method is used to retrieve documents in chunks with pagination. This method supports a variety of options to configure the query to your needs. + + + The range command is stateless, meaning you need to pass all of the parameters in each subsequent request. + + +## Arguments + + + The cursor to the last retrieved document. Should be set to `0` in the initial range request. + + + A string prefix to match document IDs. All documents with IDs that start with this prefix will be retrieved. + + + The number of maximum documents wanted in the response of range. (page size) + + +## Response + + + + + The cursor for the next set of documents. When it becomes "", it means all documents were retrieved. + + + The list of documents retrieved in this range. + + + + + + +```typescript Basic +const responseRange = await index.range({ + cursor: "0", + limit: 2, +}); + +/* +{ + nextCursor: '2', + documents: [ + { id: "doc1", content: { ... }, metadata: { ... } }, + { id: "doc2", content: { ... }, metadata: { ... } } + ] +} +*/ +``` + +```typescript ID prefix +const responseRange = await index.range({ + cursor: "0", + limit: 2, + prefix: "test-", +}); + +/* +{ + nextCursor: '2', + documents: [ + { id: "test-1", content: { ... }, metadata: { ... } }, + { id: "test-2", content: { ... }, metadata: { ... } } + ] +} +*/ +``` + + diff --git a/search/sdks/ts/commands/reset.mdx b/search/sdks/ts/commands/reset.mdx new file mode 100644 index 00000000..ddddb20e --- /dev/null +++ b/search/sdks/ts/commands/reset.mdx @@ -0,0 +1,18 @@ +--- +title: Reset +--- + +The `reset` method allows you to clear all documents from a particular index. + +## Response + +`'Success'` if the database is successfully reset. + + + +```typescript Basic +const responseReset = await index.reset(); +// 'Success' +``` + + diff --git a/search/sdks/ts/commands/search.mdx b/search/sdks/ts/commands/search.mdx new file mode 100644 index 00000000..fd95dde1 --- /dev/null +++ b/search/sdks/ts/commands/search.mdx @@ -0,0 +1,68 @@ +--- +title: Search +--- + +The search method is designed to retrieve the most relevant documents from the database, using AI-powered search capabilities. This method supports a variety of options to configure the query to your needs. + + + The score returned from search requests is a normalized value between 0 and 1, where 1 indicates the highest relevance and 0 the lowest. + + +## Arguments + + + + + The search query string. + + + The maximum number of results to return. Defaults to 5. + + + Whether to enable AI-powered reranking of results. Disabled by default. + + + A metadata filter for narrowing down the search results. + + + + +## Response + + + + + The list of documents matching the search query. + + + + + + +```typescript Basic Search +const searchResults = await index.search({ + query: "space opera", + limit: 2, +}); +console.log(searchResults); +``` + +```typescript Search with Reranking +const searchResults = await index.search({ + query: "space opera", + limit: 2, + reranking: true, +}); +console.log(searchResults); +``` + +```typescript Search with Filter +const searchResults = await index.search({ + query: "space", + limit: 2, + filter: "category = 'classic'", +}); +console.log(searchResults); +``` + + diff --git a/search/sdks/ts/commands/upsert.mdx b/search/sdks/ts/commands/upsert.mdx new file mode 100644 index 00000000..240c06dc --- /dev/null +++ b/search/sdks/ts/commands/upsert.mdx @@ -0,0 +1,63 @@ +--- +title: Upsert +--- + +Used to add new documents or update an existing document. + + + You can only upsert documents with the same structure as defined in your database. + + +## Arguments + + + + + + + + + + + + +## Response + + + `'Success'` on successful operation. + + + + +```typescript Single Document +await index.upsert({ + id: "star-wars", + content: { title: "Star Wars", genre: "sci-fi" }, + metadata: { year: 1977 } +}); +``` + +```typescript Multiple Documents +await index.upsert([ + { + id: "inception", + content: { title: "Inception", genre: "action" } + metadata: { + year: 2010, + }, + }, + { ... }, +]); +``` + +```typescript Update Document +await index.upsert({ + id: "star-wars", + content: { + title: "Star Wars: Episode IV - A New Hope", + genre: "sci-fi" + }, +}); +``` + + diff --git a/search/sdks/ts/contributing.mdx b/search/sdks/ts/contributing.mdx new file mode 100644 index 00000000..17eae2e4 --- /dev/null +++ b/search/sdks/ts/contributing.mdx @@ -0,0 +1,27 @@ +--- +title: Contributing +--- + +## Preparing the environment + +This project uses [Bun](https://bun.sh/) for packaging and dependency management. Make sure you have the relevant dependencies. + +```commandline +curl -fsSL https://bun.sh/install | bash +``` + +You will also need a search database on [Upstash](https://console.upstash.com/search). + +## Code Formatting + +```bash +bun run fmt +``` + +## Running tests + +To run all the tests, make sure you have the relevant environment variables. + +```bash +bun run test +``` diff --git a/search/sdks/ts/getting-started.mdx b/search/sdks/ts/getting-started.mdx new file mode 100644 index 00000000..2cc35b3d --- /dev/null +++ b/search/sdks/ts/getting-started.mdx @@ -0,0 +1,103 @@ +--- +title: Getting Started +--- + +`@upstash/search` is a TypeScript SDK for Upstash AI Search, enabling easier operations on Search Databases with full type coverage. + +Using `@upstash/search` you can: + +- Perform AI-powered search queries with or without reranking. +- Upsert documents with metadata to an index. +- Fetch documents by their IDs. +- Delete documents from a database. +- Access database stats. +- Reset everything related to a database. + +You can find the GitHub Repository [here](https://github.com/upstash/search-js). + +## Install + + +```shell npm +npm install @upstash/search +``` + +```shell pnpm +pnpm add @upstash/search +``` + + + +## Usage + +### Initializing the client + +There are two pieces of configuration required to use the Upstash search client: a REST token and REST URL. These values can be passed using environment variables or in code through a configuration object. Find your configuration values in [the console dashboard](https://console.upstash.com/search). + +#### Using environment variables + +The environment variables used to configure the client are the following. You can follow [this guide](/search/overall/getstarted) to retrieve credentials. + +```bash +UPSTASH_SEARCH_REST_URL="your_rest_url" +UPSTASH_SEARCH_REST_TOKEN="your_rest_token" +``` + +When these environment variables are set, the client constructor does not require any additional arguments. + +```typescript +import { Search } from "@upstash/search"; + +const client = Search.fromEnv(); +const index = client.index("movies") +``` + +#### Using a configuration object + +If you prefer to pass configuration in code, the constructor accepts a config object containing the `url` and `token` values. This +could be useful if your application needs to interact with multiple databases, each with a different configuration. + +```typescript +import { Search } from "@upstash/search"; + +const client = new Search({ + url: "", + token: "", +}); + +const index = client.index("movies") +``` + +#### Typescript + +The Search SDK supports defining your content and metadata types at the index level for complete type-safety. + +```typescript {4,5,6} +import { Search } from "@upstash/search"; +const client = new Search(); + +type Content = { title: string, genre: string }; +type Metadata = { year: number }; +const index = client.index("movies"); + +await index.upsert({ + id: "document-id", + content: { title: "Star Wars", genre: "sci-fi" }, + metadata: { year: 1977 } +}) +``` + +Passing a `Content` type at the index level will provide type safety for the content coming back from or required for the following commands: +- `search` +- `upsert` +- `fetch` +- `range` + +In cases you don't want to define a content type at the index level, you can override the index level type definition for a specific command: + +```typescript +const results = await index.upsert({ + id: "id", + content: { title: "Movie title", ... } +}); +``` diff --git a/search/tutorials/nextjs.mdx b/search/tutorials/nextjs.mdx new file mode 100644 index 00000000..60b278e1 --- /dev/null +++ b/search/tutorials/nextjs.mdx @@ -0,0 +1,208 @@ +--- +title: "Next.js Search Quickstart" +--- + +### Create a Search Database +Follow the instructions in the [Getting Started guide](/search/overall/getstarted) to create a Search Database. + +### Project Setup + +Let's create a new Next.js application with App Router and install `@upstash/search` package. + +```shell +npx create-next-app@latest search-app +cd search-app +npm install @upstash/search +``` + +### Add Environment Variables + +Find the environment variables from your database dashboard and add them to your `.env` file: +```env +UPSTASH_SEARCH_REST_URL= +UPSTASH_SEARCH_REST_TOKEN= +``` + +### Create a Route to Upsert Documents +Create an API route in `app/api/upsert/route.ts`: +```typescript +import { Search } from "@upstash/search"; + +const client = new Search({ + url: process.env.UPSTASH_SEARCH_REST_URL, + token: process.env.UPSTASH_SEARCH_REST_TOKEN, +}); + +const index = client.index("my-index"); + +export async function POST() { + await index.upsert([ + { + id: "film-1", + content: { title: "Inception", description: "A mind-bending thriller about dreams within dreams." }, + metadata: { genre: "Sci-Fi", year: 2010 }, + }, + { + id: "film-2", + content: { title: "The Godfather", description: "A story about a powerful Italian-American crime family." }, + metadata: { genre: "Crime", year: 1972 }, + }, + { + id: "film-3", + content: { title: "The Dark Knight", description: "A gritty tale of Batman's fight against the Joker." }, + metadata: { genre: "Action", year: 2008 }, + }, + ]); + return new Response(JSON.stringify({ message: "Documents upserted successfully" }), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +} + +``` + +### Create a Route to Search Documents +Create an API route in `app/api/search/route.ts`: +```typescript +import { Search } from "@upstash/search"; + +const client = new Search({ + url: process.env.UPSTASH_SEARCH_REST_URL, + token: process.env.UPSTASH_SEARCH_REST_TOKEN, +}); + +const index = client.index("my-index"); + +export async function POST(req: Request) { + const { query } = await req.json() as { query: string } + + const results = await index.search({ query }); + return new Response(JSON.stringify(results), { + status: 200, + headers: { "Content-Type": "application/json" }, + }); +} + +``` + +### Create a Simple Page +Add the following code in `app/page.tsx`: +```typescript +"use client"; + +import { useState } from "react"; + +interface SearchResult { + id: string; + content: Record; + metadata: Record; + score: number; +} + +export default function Home() { + const [searchResults, setSearchResults] = useState([]); + const [query, setQuery] = useState(""); + const [isUpserting, setIsUpserting] = useState(false); + const [upsertSuccess, setUpsertSuccess] = useState(false); + + const upsertData = async () => { + setIsUpserting(true); + setUpsertSuccess(false); + await fetch("/api/upsert", { method: "POST" }); + setIsUpserting(false); + setUpsertSuccess(true); + }; + + const search = async () => { + const res = await fetch(`/api/search`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query }), + }); + const data = await res.json(); + setSearchResults(data || []); + }; + + return ( +
+
+
+

Search App

+

+ Upsert data and search through the database. +

+
+ +
+ + {upsertSuccess && ( +

+ Data upserted successfully! +

+ )} +
+ +
+
+ setQuery(e.target.value)} + placeholder="Search..." + className="flex-1 border border-emerald-300 rounded-md px-4 py-2 text-gray-800 focus:outline-none focus:ring-2 focus:ring-emerald-500" + /> + +
+
+ +
    + {searchResults.map((result, index) => ( +
  • +

    ID: {result.id}

    +

    Content: {JSON.stringify(result.content)}

    +

    Metadata: {JSON.stringify(result.metadata)}

    +

    Score: {result.score}

    +
  • + ))} +
+
+
+ ); +} + +``` + +### Start the Project +Run the following command to start the development server: +```bash +npm run dev +``` + +Open your browser and navigate to `http://localhost:3000` to test the application. + +You can click the `Upsert Data` button to add three films to your database and then use the search bar to make a query. + + +### Next Steps + +Learn more about: +- [Typescript SDK](/search/sdks/ts/getting-started) +- [Content and Metadata fields](/search/features/content-and-metadata) diff --git a/vector/features/filtering.mdx b/vector/features/filtering.mdx index a6ad9219..390450b8 100644 --- a/vector/features/filtering.mdx +++ b/vector/features/filtering.mdx @@ -2,7 +2,7 @@ title: Metadata Filtering --- -You can further limit the vector similarity search by providing a filter based on a specific metadata criteria. +You can further restrict the vector similarity search by providing a filter based on a specific metadata criteria. Queries with metadata filters only return vectors which have metadata matching with the filter. @@ -159,7 +159,7 @@ curl $UPSTASH_VECTOR_REST_URL/query \ #### Equals (=) -The `equals` operator filters keys whose value is equal to given literal. +The `equals` operator filters keys whose values are equal to the given literal. It is applicable to _string_, _number_, and _boolean_ values. @@ -169,7 +169,7 @@ country = 'Turkey' AND population = 15460000 AND is_capital = false #### Not Equals (!=) -The `not equals` operator filters keys whose value is not equal to given literal. +The `not equals` operator filters keys whose values are not equal to the given literal. It is applicable to _string_, _number_, and _boolean_ values. @@ -179,7 +179,7 @@ country != 'Germany' AND population != 12500000 AND is_capital != true #### Less Than (\<) -The `less than` operator filters keys whose value is less than the given literal. +The `less than` operator filters keys whose values are less than the given literal. It is applicable to _number_ values. @@ -189,7 +189,7 @@ population < 20000000 OR geography.coordinates.longitude < 30.0 #### Less Than or Equals (\<=) -The `less than or equals` operator filters keys whose value is less than or equal to the given literal. +The `less than or equals` operator filters keys whose values are less than or equal to the given literal. It is applicable to _number_ values. @@ -199,7 +199,7 @@ population <= 20000000 OR geography.coordinates.longitude <= 30.0 #### Greater Than (>) -The `greater than` operator filters keys whose value is greater than the given literal. +The `greater than` operator filters keys whose values are greater than the given literal. It is applicable to _number_ values. @@ -209,7 +209,7 @@ population > 10000000 OR geography.coordinates.latitude > 39.5 #### Greater Than or Equals (>=) -The `greater than or equals` operator filters keys whose value is greater than or equal to the given literal. +The `greater than or equals` operator filters keys whose values are greater than or equal to the given literal. It is applicable to _number_ values. @@ -219,7 +219,7 @@ population >= 10000000 OR geography.coordinates.latitude >= 39.5 #### Glob -The `glob` operator filters keys whose value matches the given UNIX glob pattern. +The `glob` operator filters keys whose values match with the given UNIX glob pattern. It is applicable to _string_ values. @@ -244,7 +244,7 @@ city GLOB '?[sz]*[^m-z]' #### Not Glob -The `not glob` operator filters keys whose value does not match the given UNIX glob pattern. +The `not glob` operator filters keys whose values do not match with the given UNIX glob pattern. It is applicable to _string_ values. @@ -258,7 +258,7 @@ city NOT GLOB 'A*' #### In -The `in` operator filters keys whose value is equal to any of the given literals. +The `in` operator filters keys whose values are equal to any of the given literals. It is applicable to _string_, _number_, and _boolean_ values. @@ -274,7 +274,7 @@ country = 'Germany' OR country = 'Turkey' OR country = 'France' #### Not In -The `not in` operator filters keys whose value is not equal to any of the given literals. +The `not in` operator filters keys whose values are not equal to any of the given literals. It is applicable to _string_, _number_, and _boolean_ values. @@ -290,9 +290,9 @@ economy.currency != 'USD' AND economy.currency != 'EUR' #### Contains -The `contains` operator filters keys whose value contains the given literal. +The `contains` operator filters keys whose values contain the given literal. -It is applicable to `array` values. +It is applicable to _array_ values. ```SQL economy.major_industries CONTAINS 'Tourism' @@ -300,9 +300,9 @@ economy.major_industries CONTAINS 'Tourism' #### Not Contains -The `not contains` operator filters keys whose value does not contain the given literal. +The `not contains` operator filters keys whose values do not contain the given literal. -It is applicable to `array` values. +It is applicable to _array_ values. ```SQL economy.major_industries NOT CONTAINS 'Steel Production' @@ -310,7 +310,7 @@ economy.major_industries NOT CONTAINS 'Steel Production' #### Has Field -The `has field` operator filters keys which having the given JSON field. +The `has field` operator filters keys which have the given JSON field. ```SQL @@ -319,7 +319,7 @@ HAS FIELD geography.coordinates #### Has Not Field -The `has not field` operator filters keys which not having the given JSON field. +The `has not field` operator filters keys which do not have the given JSON field. ```SQL @@ -335,14 +335,14 @@ compound filters. country = 'Turkey' AND population > 10000000 ``` -Boolean operators can be grouped with parentheses to have higher precendence. +Boolean operators can be grouped with parentheses to have higher precedence. ```SQL country = 'Turkey' AND (population > 10000000 OR is_capital = false) ``` -When no parentheses are provided in ambigous filters, `AND` will have higher -precendence than `OR`. So, the filter +When no parentheses are provided in ambiguous filters, `AND` will have higher +precedence than `OR`. So, the filter ```SQL country = 'Turkey' AND population > 10000000 OR is_capital = false @@ -378,7 +378,7 @@ economy.major_industries[0] = 'Tourism' Also, it is possible to index from the back using the `#` character with negative values. `#` can be thought as the number of elements in the array, so `[#-1]` would reference the -last character. +last element. ```SQL economy.major_industries[#-1] = 'Finance' diff --git a/vector/sdks/ts/commands/info.mdx b/vector/sdks/ts/commands/info.mdx index 24b967d0..1f9fb0d7 100644 --- a/vector/sdks/ts/commands/info.mdx +++ b/vector/sdks/ts/commands/info.mdx @@ -26,10 +26,10 @@ Used to retrieve the stats of an index. A map of namespaces to their information in the following format - The total number of vectors in the index, that are ready to use. + The total number of vectors in the namespace, that are ready to use. - The number of vectors in the index, that is still processing and not ready to + The number of vectors in the namespace, that is still processing and not ready to use.