ExTypesense.Document (ExTypesense v2.0.0)

View Source

Module for CRUD operations for documents. Refer to this doc guide.

Summary

Functions

Deletes all documents in a collection.

Delete an individual document from a collection by using its document ID.

Deletes documents in a collection by query.

Export all documents in a collection in JSON lines format.

Fetch an individual document from a collection by using its ID.

Imports/Indexes multiple documents via maps.

Indexes a single document using struct or map. When using struct, the pk maps to document's id as string.

Update an single document using struct or map. The update can be partial.

Update documents with conditional query

Functions

delete_all_documents(collection_name)

(since 1.0.0)
@spec delete_all_documents(module() | String.t()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Deletes all documents in a collection.

On using this function

As of this writing (v0.5.0), there's no built-in way of deleting all documents via Typesense docs. This function uses delete_documents_by_query/2 under the hood.

delete_all_documents(module, opts)

(since 1.0.0)
@spec delete_all_documents(
  module() | String.t(),
  keyword()
) :: {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as delete_all_documents/1.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.delete_all_documents("persons", conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.delete_all_documents("persons", conn: conn)

iex> opts = [conn: conn]
iex> ExTypesense.delete_all_documents(MyModule.Accounts.Person, opts)

delete_document(document)

(since 1.0.0)
@spec delete_document(map() | struct()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Delete an individual document from a collection by using its document ID.

Options

  • ignore_not_found: (Boolean) Ignore the error and treat the deletion as success. This option is only available when payload is map, not struct.

Deleting a document by id

Deleting a document means the Typesense document ID, NOT the ID of the record itself. If you want to delete the ID of record, use ExTypesense.delete_documents_by_query/2

Examples

iex> ExTypesense.create_collection(Post)
iex> post = Post |> limit(1) |> Repo.one()
iex> ExTypesense.index_document(post)
{:ok,
  %{
    id: "1",
    posts_id: 99,
    title: "our first post",
    collection_name: "posts"
  }
}
iex> ExTypesense.delete_document(post)

iex> schema = %{
...>   name: "posts",
...>   fields: [
...>     %{name: "title", type: "string"}
...>   ],
...> }
...> ExTypesense.create_collection(schema)
iex> post =
...>  %{
...>    id: "12",
...>    collection_name: "posts",
...>    posts_id: 22,
...>    title: "the quick brown fox"
...>  }
iex> ExTypesense.index_document(post)
iex> ExTypesense.delete_document("posts", "12", ignore_not_found: true)
{:ok,
  %{
    id: "12",
    posts_id: 22,
    title: "the quick brown fox",
    collection_name: "posts"
  }
}

delete_document(record, opts)

(since 1.0.0)
@spec delete_document(
  map() | OpenApiTypesense.Connection.t() | String.t(),
  String.t() | keyword()
) :: {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as delete_document/1.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.delete_document(document, conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.delete_document(struct, conn: conn)

iex> opts = [ignore_not_found: true, conn: conn]
iex> ExTypesense.delete_document(struct, opts)

delete_document(coll_name, doc_id, opts)

(since 1.0.0)
@spec delete_document(String.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as delete_document/2.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.delete_document("persons", "88", conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.delete_document("persons", "88", conn: conn)

iex> opts = [ignore_not_found: true, conn: conn]
iex> ExTypesense.delete_document("persons", "88", opts)

delete_documents_by_query(module, opts)

(since 1.0.0)
@spec delete_documents_by_query(
  String.t() | module(),
  keyword()
) :: {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Deletes documents in a collection by query.

Options

  • conn: The custom connection map or struct you passed
  • batch_size: Batch size parameter controls the number of documents that should be deleted at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server.
  • filter_by: Filter results by a particular value(s) or logical expressions. multiple conditions with &&.

Filter and batch size

To delete all documents in a collection, you can use a filter that matches all documents in your collection. For eg, if you have an int32 field called popularity in your documents, you can use filter_by: "popularity:>0" to delete all documents. Or if you have a bool field called in_stock in your documents, you can use filter_by: "in_stock:[true,false]" to delete all documents.

Use the batch_size to control the number of documents that should deleted at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server.

Filter parameters can be found here: https://typesense.org/docs/latest/api/search.html#filter-parameters

Examples

iex> query = [filter_by: "num_employees:>100", batch_size: 100]
iex> ExTypesense.delete_documents_by_query(Employee, query)
{:ok, [...]}

iex> conn = %{api_key: xyz, host: ...}
iex> opts = Keyword.put(query, :conn, conn)
iex> ExTypesense.delete_documents_by_query(Employee, opts)

export_documents(collection_name)

(since 1.0.0)
@spec export_documents(String.t() | module()) ::
  {:ok, String.t()} | {:error, OpenApiTypesense.ApiResponse.t()}

Export all documents in a collection in JSON lines format.

Options

  • filter_by: Filter conditions for refining your search results. Separate multiple conditions with &&.
  • include_fields: List of fields from the document to include in the search result
  • exclude_fields: List of fields from the document to exclude in the search result

export_documents(module, opts)

(since 1.0.0)
@spec export_documents(
  String.t() | module(),
  keyword()
) :: {:ok, String.t()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as export_documents/1.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.export_documents("persons", conn: conn)
iex> ExTypesense.export_documents(MyModule.Accounts.Person, conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.export_documents("persons", conn: conn)

iex> opts = [conn: conn]
iex> ExTypesense.export_documents(MyModule.Accounts.Person, opts)

get_document(collection_name, document_id)

(since 1.0.0)
@spec get_document(module() | String.t(), String.t()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Fetch an individual document from a collection by using its ID.

Options

  • include_fields: (Comma-separated values) List of fields that should be present in the returned document.
  • exclude_fields: (Comma-separated values) List of fields that should not be present in the returned document.

Examples

iex> schema = %{
...>   name: "posts",
...>   fields: [
...>     %{name: "title", type: "string"}
...>   ],
...> }
...> ExTypesense.create_collection(schema)
...> post = %{
...>    id: "22"
...>    posts_id: 444,
...>    collection_name: "posts",
...>    title: "the quick brown fox"
...> }
iex> ExTypesense.index_document(post)
iex> ExTypesense.get_document("posts", "22", exclude_fields: "title,posts_id")
{:ok,
  %{
    id: "22",
    collection_name: "posts"
  }
}

get_document(module, doc_id, opts)

(since 1.0.0)
@spec get_document(module() | String.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as get_document/2.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.get_document("persons", "88", exclude_fields: "name", conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.get_document(MyModule.Accounts.Person, "88", exclude_fields: "name", conn: conn)

iex> opts = [exclude_fields: "name", conn: conn]
iex> ExTypesense.get_document(MyModule.Accounts.Person, "88", opts)

import_documents(coll_name, docs)

(since 1.0.0)
@spec import_documents(String.t() | module(), [struct()] | [map()]) ::
  {:ok, [map()]} | {:error, OpenApiTypesense.ApiResponse.t()}

Imports/Indexes multiple documents via maps.

You can feed the output file from a Typesense export operation directly as import.

Options

  • batch_size: Batch size parameter controls the number of documents that should be imported at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server.
  • return_id: Returning the id of the imported documents. If you want the import response to return the ingested document's id in the response, you can use the return_id parameter.
  • remote_embedding_batch_size: Max size of each batch that will be sent to remote APIs while importing multiple documents at once. Using lower amount will lower timeout risk, but increase number of requests made. Default is 200.
  • remote_embedding_timeout_ms: How long to wait until an API call to a remote embedding service is considered a timeout during indexing. Default is 60_000 ms
  • remote_embedding_num_tries: The number of times to retry an API call to a remote embedding service on failure during indexing. Default is 2.
  • return_doc: Returns the entire document back in response.
  • action: Additional action to perform
  • dirty_values: Dealing with Dirty Data

Examples

iex> schema = %{
...>   name: "posts",
...>   fields: [
...>     %{name: "title", type: "string"}
...>   ],
...> }
...> ExTypesense.create_collection(schema)

# doesn't matter if atom or string keys
# import using a list of maps
iex> posts = [
...>   %{title: "the quick brown fox"},
...>   %{title: "jumps over the lazy dog"}
...> ]
...> ExTypesense.import_documents("posts", posts)
{:ok, [%{"success" => true}, %{"success" => true}]}

# import using Ecto records
iex> posts = MyApp.Blog.Post |> Repo.all()
...> ExTypesense.import_documents("posts", posts)

import_documents(module, docs, opts)

(since 1.0.0)
@spec import_documents(String.t() | module(), [struct()] | [map()], keyword()) ::
  {:ok, [map()]} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as import_documents/2.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.import_documents("users", documents, conn: conn)
iex> ExTypesense.import_documents(MyApp.Accounts.User, documents, conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.import_documents(MyApp.Accounts.User, structs, conn: conn)
iex> ExTypesense.import_documents("users", [%MyApp.Accounts.User{}], conn: conn)

iex> opts = [conn: conn]
iex> ExTypesense.import_documents("users", documents, opts)

index_document(document)

(since 1.0.0)
@spec index_document(map() | struct()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Indexes a single document using struct or map. When using struct, the pk maps to document's id as string.

indexing your document as a map

when using maps as documents using index_document/1, you should pass a key named collection_name.

on using struct

Please refer on this page for more info on how to setup with Ecto Schema.

Options

  • action: "create" (default), "upsert", "update", "emplace"
  • dirty_values: Dealing with Dirty Data

Examples

iex> schema = %{
...>   name: "posts",
...>   fields: [
...>     %{name: "title", type: "string"}
...>     %{name: "posts_id", type: "int32"}
...>     %{name: "description", type: "string"}
...>   ],
...> }
iex> ExTypesense.create_collection(schema)
iex> body =
...>  %{
...>    id: "34", # you can omit this key, Typesense will generate for you.
...>    posts_id: 28,
...>    title: "the quick brown fox",
...>    description: "jumps over the lazy dog"
...>  }
iex> ExTypesense.index_document("posts", body)
{:ok,
  %{
    id: "34",
    posts_id: 28,
    title: "the quick brown fox",
    description: "jumps over the lazy dog"
  }
}

iex> MyApp.Blog.Post |> ExTypesense.create_collection()
iex> post = MyApp.Blog.get_post!(24)
iex> ExTypesense.index_document(post)

index_document(record, opts)

(since 0.1.0)
@spec index_document(map() | struct() | String.t(), map() | keyword()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as index_document/1.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.index_document("persons", document, conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.index_document(document, conn: conn)
iex> ExTypesense.index_document(struct, conn: conn)

iex> opts = [action: "upsert", conn: conn]
iex> ExTypesense.index_document(struct, opts)

index_document(collection_name, body, opts)

(since 1.0.0)
@spec index_document(String.t(), map(), keyword()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as index_document/2.

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.index_document("persons", document, action: "update", conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.index_document("persons", document, conn: conn)

iex> opts = [action: "upsert", conn: conn]
iex> ExTypesense.index_document("persons", document, opts)

update_document(document)

(since 1.0.0)
@spec update_document(map() | struct()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Update an single document using struct or map. The update can be partial.

Note: the return type for struct and map are different. See examples below.

indexing your document as a map

when using map as document, you should pass a key named collection_name.

Options

  • dirty_values: Dealing with Dirty Data

Examples

iex> schema = %{
...>   name: "posts",
...>   fields: [
...>     %{name: "title", type: "string"}
...>   ],
...> }
iex> ExTypesense.create_collection(schema)
iex> post =
...>  %{
...>    id: "94",
...>    collection_name: "posts",
...>    posts_id: 94,
...>    title: "the quick brown fox"
...>  }
iex> ExTypesense.index_document(post)
iex> updated_post =
...>  %{
...>    id: "94",
...>    collection_name: "posts",
...>    posts_id: 94,
...>    title: "test"
...>  }
iex> ExTypesense.update_document(updated_post)
{:ok,
  %{
    id: "94",
    collection_name: "posts",
    posts_id: 94,
    title: "sample post"
  }
}

iex> person = Accounts.fetch_person!(12)
...> ExTypesense.update_document(person)
{:ok,
  %OpenApiTypesense.Documents{
    num_deleted: nil,
    num_updated: 1
  }
}

update_document(record, opts)

(since 1.0.0)
@spec update_document(
  map() | struct(),
  keyword()
) :: {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Same as update_document/1.

Options

  • conn: The custom connection map or struct you passed

Examples

iex> conn = %{api_key: xyz, host: ...}
iex> ExTypesense.update_document(document, conn: conn)

iex> conn = OpenApiTypesense.Connection.new()
iex> ExTypesense.update_document(%User{...}, conn: conn)

iex> opts = [dirty_values: "reject", conn: conn]
iex> ExTypesense.update_document(document, opts)

update_documents_by_query(module, body, opts)

(since 1.0.0)
@spec update_documents_by_query(String.t() | module(), map(), keyword()) ::
  {:ok, map()} | {:error, OpenApiTypesense.ApiResponse.t()}

Update documents with conditional query

The filter_by query parameter is used to filter to specify a condition against which the documents are matched. The request body contains the fields that should be updated for any documents that match the filter condition. This endpoint is only available if the Typesense server is version 0.25.0.rc12 or later.

See: https://typesense.org/docs/latest/api/search.html#filter-parameters regarding filter_by option.

Options

  • conn: The custom connection map or struct you passed
  • filter_by: Filter results by a particular value(s) or logical expressions. multiple conditions with &&.
  • action: Additional action to perform

Example

iex> body = %{
...>   "tag" => "large",
...> }

iex> conn = %{api_key: xyz, host: ...}
iex> opts = [filter_by: "num_employees:>1000", conn: conn]
iex> ExTypesense.update_documents_by_query("companies", body, opts)

iex> ExTypesense.update_documents_by_query("companies", body, action: "upsert", conn: conn)