{"id":19000434,"url":"https://github.com/typesense/typesense-swift","last_synced_at":"2025-08-21T00:31:36.247Z","repository":{"id":40442575,"uuid":"392906518","full_name":"typesense/typesense-swift","owner":"typesense","description":"Swift Client for Typesense ⚡️🔎","archived":false,"fork":false,"pushed_at":"2024-11-06T04:34:36.000Z","size":10207,"stargazers_count":39,"open_issues_count":4,"forks_count":16,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-12-11T12:12:02.647Z","etag":null,"topics":["ios","search","swift","typesense"],"latest_commit_sha":null,"homepage":"https://typesense.org/docs/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typesense.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-08-05T04:54:54.000Z","updated_at":"2024-11-05T17:45:04.000Z","dependencies_parsed_at":"2024-08-07T19:33:47.456Z","dependency_job_id":null,"html_url":"https://github.com/typesense/typesense-swift","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typesense%2Ftypesense-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typesense","download_url":"https://codeload.github.com/typesense/typesense-swift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230379996,"owners_count":18216847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","search","swift","typesense"],"created_at":"2024-11-08T18:07:12.984Z","updated_at":"2024-12-19T17:09:37.059Z","avatar_url":"https://github.com/typesense.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Typesense Swift\n\nA great new way to implement your searches on iOS using [Typesense](https://github.com/typesense/typesense) ⚡️🔍✨ Typesense Swift is a high level wrapper that helps you easily implement searching using Typesense.\n\n## Installation\n\nAdd `Typesense Swift` Swift Package to your project. You can refer [Apple's Documentation](https://developer.apple.com/documentation/swift_packages/adding_package_dependencies_to_your_app) to add Typesense Swift as a dependency to your iOS Project. You can also import Typesense into your own Swift Package by adding this line to dependencies array of `Package.swift`:\n\n```swift\n...\ndependencies: [\n           .package(url: \"https://github.com/typesense/typesense-swift\", .upToNextMajor(from: \"1.0.0\"),\n],\n...\n```\n\n## Usage\n\n### Setting up the client\n\nImport Typesense onto your Swift Project:\n\n```swift\nimport Typesense\n```\n\nDeclare the Typesense nodes that are available as `Node` members:\n\n```swift\nlet node1 = Node(url: \"http://localhost:8108\") // or\nlet node2 = Node(host: \"xxx-1.a1.typesense.net\", port: \"443\", nodeProtocol: \"https\")\n```\n\nCreate a configuration and hence a client with the Nodes mentioned:\n\n```swift\nlet myConfig = Configuration(nodes: [node1, node2], apiKey: \"coolstuff\")\n\nlet client = Client(config: myConfig)\n```\n\nYou can use Typesense parameters like `nearestNode` and `connectionTimeoutSeconds` while creating the configuration. You can also pass in a `logger` parameter to debug the code like this:\n\n```swift\nlet myConfig = Configuration(nodes: [node1, node2], apiKey: \"coolstuff\", logger: Logger(debugMode: true))\n```\n\n### Indexing documents\n\nYou can create a collection by first defining a collection schema:\n\n```swift\nlet myCoolSchema = CollectionSchema(name: \"schools\", fields: [Field(name: \"school_name\", type: \"string\"), Field(name: \"num_students\", type: \"int32\"), Field(name: \"country\", type: \"string\", facet: true)], defaultSortingField: \"num_students\")\n\nlet (data, response) = try await client.collections.create(schema: myCoolSchema)\n```\n\nDefine the structure of your document as per your collection, and index it by inserting/upserting it to the collection:\n\n```swift\nstruct School: Codable {\n    var id: String\n    var school_name: String\n    var num_students: Int\n    var country: String\n}\n\nlet document = School(id: \"7\", school_name: \"Hogwarts\", num_students: 600, country: \"United Kingdom\")\nlet documentData = try JSONEncoder().encode(document)\nlet (data, response) = try await client.collection(name: \"schools\").documents().create(document: documentData)\n//or\nlet (data, response) = try await client.collection(name: \"schools\").documents().upsert(document: documentData)\n```\n\nYou can perform CRUD actions to `Collections` and `Documents` that belong to a certain collection. You can also use `.importBatch()` on the `documents()` method to import and index a batch of documents (in .jsonl format).\n\n### Searching\n\nDefine your [search parameters](https://typesense.org/docs/27.0/api/search.html#search-parameters) clearly and then perform the search operation by mentioning your Document Type:\n\n```swift\nlet searchParameters = SearchParameters(q: \"hog\", queryBy: \"school_name\", filterBy: \"num_students:\u003e500\", sortBy: \"num_students:desc\")\n\nlet (data, response) = try await client.collection(name: \"schools\").documents().search(searchParameters, for: School.self)\n```\n\nThis returns a `SearchResult` object as the data, which can be further parsed as desired.\n\n### Bulk import documents\n\n```swift\nlet jsonL = Data(\"{}\".utf8)\nlet (data, response) = try await client.collection(name: \"companies\").documents().importBatch(jsonL, options: ImportDocumentsParameters(\n    action: .upsert,\n    batchSize: 10,\n    dirtyValues: .drop,\n    remoteEmbeddingBatchSize: 10,\n    returnDoc: true,\n    returnId: false\n))\n```\n\n### Update multiple documents by query\n\n```swift\nlet (data, response) = try await client.collection(name: \"companies\").documents().update(\n    document: [\"company_size\": \"large\"],\n    options: UpdateDocumentsByFilterParameters(filterBy: \"num_employees:\u003e1000\")\n)\n```\n\n### Delete multiple documents by query\n\n```swift\nlet (data, response) = try await client.collection(name: \"companies\").documents().delete(\n    options: DeleteDocumentsParameters(filterBy: \"num_employees:\u003e100\")\n)\n```\n\n### Export documents\n\n```swift\nlet (data, response) = try await client.collection(name: \"companies\").documents().export(options: ExportDocumentsParameters(excludeFields: \"country\"))\n```\n\n### Create or update a collection alias\n\n```swift\nlet schema = CollectionAliasSchema(collectionName: \"companies_june\")\nlet (data, response) = try await client.aliases().upsert(name: \"companies\", collection: schema)\n```\n\n### Retrieve all aliases\n\n```swift\nlet (data, response) = try await client.aliases().retrieve()\n```\n\n### Retrieve an alias\n\n```swift\nlet (data, response) = try await client.aliases().retrieve(name: \"companies\")\n```\n\n### Delete an alias\n\n```swift\nlet (data, response) = try await client.aliases().delete(name: \"companies\")\n```\n\n### Create an API key\n\n```swift\nlet adminKey = ApiKeySchema(_description: \"Test key with all privileges\", actions: [\"*\"], collections: [\"*\"])\nlet (data, response) = try await client.keys().create(adminKey)\n```\n\n### Retrieve all API keys\n\n```swift\nlet (data, response) = try await client.keys().retrieve()\n```\n\n### Retrieve an API key\n\n```swift\nlet (data, response) = try await client.keys().retrieve(id: 1)\n```\n\n### Delete an API key\n\n```swift\nlet (data, response) = try await client.keys().delete(id: 1)\n```\n\n### Create a conversation model\n\n```swift\nlet schema = ConversationModelCreateSchema(\n    _id: \"conv-model-1\",\n    modelName: \"openai/gpt-3.5-turbo\",\n    apiKey: \"OPENAI_API_KEY\",\n    historyCollection: \"conversation_store\",\n    systemPrompt: \"You are an assistant for question-answering...\",\n    ttl: 10000,\n    maxBytes: 16384\n)\nlet (data, response) = try await client.conversations().models().create(params: schema)\n```\n\n### Retrieve all conversation models\n\n```swift\nlet (data, response) = try await client.conversations().models().retrieve()\n```\n\n### Retrieve a conversation model\n\n```swift\nlet (data, response) = try await client.conversations().model(modelId: \"conv-model-1\").retrieve()\n```\n\n### Update a conversation model\n\n```swift\nlet (data, response) = try await client.conversations().model(modelId: \"conv-model-1\").update(params: ConversationModelUpdateSchema(\n    systemPrompt: \"...\"\n))\n```\n\n### Delete a conversation model\n\n```swift\nlet (data, response) = try await client.conversations().model(modelId: \"conv-model-1\").delete()\n```\n\n### Create or update an override\n\n```swift\nlet schema = SearchOverrideSchema\u003cMetadataType\u003e(\n    rule: SearchOverrideRule(tags: [\"test\"], query: \"apple\", match: SearchOverrideRule.Match.exact, filterBy: \"employees:=50\"),\n    includes: [SearchOverrideInclude(_id: \"include-id\", position: 1)],\n    excludes: [SearchOverrideExclude(_id: \"exclude-id\")],\n    filterBy: \"test:=true\",\n    removeMatchedTokens: false,\n    metadata: MetadataType(message: \"test-json\"),\n    sortBy: \"num_employees:desc\",\n    replaceQuery: \"test\",\n    filterCuratedHits: false,\n    effectiveFromTs: 123,\n    effectiveToTs: 456,\n    stopProcessing: false\n)\nlet (data, response) = try await client.collection(name: \"books\").overrides().upsert(overrideId: \"test-id\", params: schema)\n```\n\n### Retrieve all overrides\n\n```swift\nlet (data, response) = try await client.collection(name: \"books\").overrides().retrieve(metadataType: Never.self)\n```\n\n### Retrieve an override\n\n```swift\nlet (data, response) = try await client.collection(name: \"books\").override(\"test-id\").retrieve(metadataType: MetadataType.self)\n```\n\n### Delete an override\n\n```swift\nlet (data, response) = try await client.collection(name: \"books\").override(\"test-id\").delete()\n```\n\n### Create or update a preset\n\n```swift\nlet schema = PresetUpsertSchema(\n    value: PresetValue.singleCollectionSearch(SearchParameters(q: \"apple\"))\n    // or: value: PresetValue.multiSearch(MultiSearchSearchesParameter(searches: [MultiSearchCollectionParameters(q: \"apple\")]))\n)\nlet (data, response) = try await client.presets().upsert(presetName: \"listing_view\", params: schema)\n```\n\n### Retrieve all presets\n\n```swift\nlet (data, response) = try await client.presets().retrieve()\n```\n\n### Retrieve a preset\n\n```swift\nlet (data, response) = try await client.preset(\"listing_view\").retrieve()\n\nswitch data?.value {\n    case .singleCollectionSearch(let value):\n        print(value)\n    case .multiSearch(let value):\n        print(value)\n}\n```\n\n### Delete a preset\n\n```swift\nlet (data, response) = try await client.preset(\"listing_view\").delete()\n```\n\n### Create or update a stopwords set\n\n```swift\nlet schema = StopwordsSetUpsertSchema(\n    stopwords: [\"states\",\"united\"],\n    locale: \"en\"\n)\nlet (data, response) = try await client.stopwords().upsert(stopwordsSetId: \"stopword_set1\", params: schema)\n```\n\n### Retrieve all stopwords sets\n\n```swift\nlet (data, response) = try await client.stopwords().retrieve()\n```\n\n### Retrieve a stopwords set\n\n```swift\nlet (data, response) = try await client.stopword(\"stopword_set1\").retrieve()\n```\n\n### Delete a stopwords set\n\n```swift\nlet (data, response) = try await client.stopword(\"stopword_set1\").delete()\n```\n\n### Create or update a synonym\n\n```swift\nlet schema = SearchSynonymSchema(synonyms: [\"blazer\", \"coat\", \"jacket\"])\nlet (data, response) = try await client.collection(name: \"products\").synonyms().upsert(id: \"coat-synonyms\", schema)\n```\n\n### Retrieve all synonyms\n\n```swift\nlet (data, response) = try await client.collection(name: \"products\").synonyms().retrieve()\n```\n\n### Retrieve a synonym\n\n```swift\nlet (data, response) = try await client.collection(name: \"products\").synonyms().retrieve(id: \"coat-synonyms\")\n```\n\n### Delete a synonym\n\n```swift\nlet (data, response) = try await myClient.collection(name: \"products\").synonyms().delete(id: \"coat-synonyms\")\n```\n\n### Retrieve debug information\n\n```swift\nlet (data, response) = try await client.operations().getDebug()\n```\n\n### Retrieve health status\n\n```swift\nlet (data, response) = try await client.operations().getHealth()\n```\n\n### Retrieve API stats\n\n```swift\nlet (data, response) = try await client.operations().getStats()\n```\n\n### Retrieve Cluster Metrics\n\n```swift\nlet (data, response) = try await client.operations().getMetrics()\n```\n\n### Re-elect Leader\n\n```swift\nlet (data, response) = try await client.operations().vote()\n```\n\n### Toggle Slow Request Log\n\n```swift\nlet (data, response) = try await client.operations().toggleSlowRequestLog(seconds: 2)\n```\n\n### Clear cache\n\n```swift\nlet (data, response) = try await client.operations().clearCache()\n```\n\n### Create Snapshot (for backups)\n\n```swift\nlet (data, response) = try await client.operations().snapshot(path: \"/tmp/typesense-data-snapshot\")\n```\n\n## Contributing\n\nIssues and pull requests are welcome on GitHub at [Typesense Swift](https://github.com/typesense/typesense-swift). Do note that the Models used in the Swift client are generated by [Swagger-Codegen](https://github.com/swagger-api/swagger-codegen) and are automated to be modified in order to prevent major errors. So please do use the shell script that is provided in the repo to generate the models:\n\n```shell\nsh get-models.sh\n```\n\nThe generated Models (inside the Models directory) are to be used inside the Models directory of the source code as well. Models need to be generated as and when the [Typesense-Api-Spec](https://github.com/typesense/typesense-api-spec) is updated.\n\n## TODO: Features\n\n- Scoped Search Key\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypesense%2Ftypesense-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypesense%2Ftypesense-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypesense%2Ftypesense-swift/lists"}