Skip to content

Commit

Permalink
Merge pull request #32 from phiHero/master
Browse files Browse the repository at this point in the history
Feat: add support for overrides / curation
  • Loading branch information
jasonbosco authored Aug 2, 2024
2 parents fab8757 + d699966 commit ac11f7a
Show file tree
Hide file tree
Showing 29 changed files with 869 additions and 287 deletions.
22 changes: 14 additions & 8 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
name: tests
on: [push, pull_request]

on:
push:
paths-ignore:
- '**/*.md'
pull_request:
paths-ignore:
- '**/*.md'

# Cancel previous running if a new push is made
# Source: https://stackoverflow.com/a/72408109/123545
Expand All @@ -11,12 +18,11 @@ jobs:
test:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- uses: actions/checkout@v4
- name: Install and start dependencies
run: |
brew install docker
brew install colima
# https://github.com/abiosoft/colima/issues/424#issuecomment-1335912905
colima delete
colima start --arch x86_64
Expand All @@ -26,16 +32,16 @@ jobs:
mkdir $(pwd)/typesense-data
docker run -p 8108:8108 \
-d \
-v$(pwd)/typesense-data:/data typesense/typesense:0.25.2 \
-v$(pwd)/typesense-data:/data typesense/typesense:26.0 \
--data-dir /data \
--api-key=xyz \
--enable-cors
shell: bash

- name: Set up Xcode 13.2.1
- name: Set up Xcode
uses: maxim-lobanov/[email protected]
with:
xcode-version: '13.2.1'
xcode-version: latest-stable

- name: Run Tests
- name: Run tests
run: swift test
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let myConfig = Configuration(nodes: [node1, node2], apiKey: "coolstuff")

let client = Client(config: myConfig)
```

You 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:

```swift
Expand All @@ -50,7 +51,7 @@ You can create a collection by first defining a collection schema:

```swift
let 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")

let (data, response) = try await client.collections.create(schema: myCoolSchema)
```

Expand All @@ -67,9 +68,10 @@ struct School: Codable {
let document = School(id: "7", school_name: "Hogwarts", num_students: 600, country: "United Kingdom")
let documentData = try JSONEncoder().encode(document)
let (data, response) = try await client.collection(name: "schools").documents().create(document: documentData)
//or
//or
let (data, response) = try await client.collection(name: "schools").documents().upsert(document: documentData)
```

You 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).

### Searching
Expand All @@ -81,8 +83,47 @@ let searchParameters = SearchParameters(q: "hog", queryBy: "school_name", filter

let (data, response) = try await client.collection(name: "schools").documents().search(searchParameters, for: School.self)
```

This returns a `SearchResult` object as the data, which can be further parsed as desired.

### Create or update an override

```swift
let schema = SearchOverrideSchema<MetadataType>(
rule: SearchOverrideRule(tags: ["test"], query: "apple", match: SearchOverrideRule.Match.exact, filterBy: "employees:=50"),
includes: [SearchOverrideInclude(_id: "include-id", position: 1)],
excludes: [SearchOverrideExclude(_id: "exclude-id")],
filterBy: "test:=true",
removeMatchedTokens: false,
metadata: MetadataType(message: "test-json"),
sortBy: "num_employees:desc",
replaceQuery: "test",
filterCuratedHits: false,
effectiveFromTs: 123,
effectiveToTs: 456,
stopProcessing: false
)
let (data, response) = try await client.collection(name: "books").overrides().upsert(overrideId: "test-id", params: schema)
```

### Retrieve all overrides

```swift
let (data, response) = try await client.collection(name: "books").overrides().retrieve(metadataType: Never.self )
```

### Retrieve an override

```swift
let (data, response) = try await client.collection(name: "books").override("test-id").retrieve(metadataType: MetadataType.self )
```

### Delete an override

```swift
let (data, response) = try await client.collection(name: "books").override("test-id").delete()
```

## Contributing

Issues 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:
Expand All @@ -95,6 +136,5 @@ The generated Models (inside the Models directory) are to be used inside the Mod

## TODO: Features

- Curation API
- Dealing with Dirty Data
- Scoped Search Key
19 changes: 11 additions & 8 deletions Sources/Typesense/Alias.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

public struct Alias {
var apiCall: ApiCall
Expand All @@ -9,12 +12,12 @@ public struct Alias {
apiCall = ApiCall(config: config)
self.config = config
}

public func upsert(name: String, collection: CollectionAliasSchema) async throws -> (CollectionAlias?, URLResponse?) {
let schemaData: Data?

schemaData = try encoder.encode(collection)

if let validSchema = schemaData {
let (data, response) = try await apiCall.put(endPoint: "\(RESOURCEPATH)/\(name)", body: validSchema)
if let result = data {
Expand All @@ -24,7 +27,7 @@ public struct Alias {
}
return (nil, nil)
}

public func retrieve(name: String) async throws -> (CollectionAlias?, URLResponse?) {
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/\(name)")
if let result = data {
Expand All @@ -36,7 +39,7 @@ public struct Alias {
}
return (nil, nil)
}

public func retrieve() async throws -> (CollectionAliasesResponse?, URLResponse?) {
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)")
if let result = data {
Expand All @@ -45,7 +48,7 @@ public struct Alias {
}
return (nil, nil)
}

public func delete(name: String) async throws -> (CollectionAlias?, URLResponse?) {
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)/\(name)")
if let result = data {
Expand All @@ -57,6 +60,6 @@ public struct Alias {
}
return (nil, nil)
}


}
9 changes: 6 additions & 3 deletions Sources/Typesense/AnalyticsRule.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

public struct AnalyticsRule {
var name: String
Expand All @@ -7,7 +10,7 @@ public struct AnalyticsRule {
self.name = name
self.apiCall = apiCall
}

public func retrieve() async throws -> (AnalyticsRuleSchema?, URLResponse?) {
let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
if let result = data {
Expand All @@ -19,7 +22,7 @@ public struct AnalyticsRule {
}
return (nil, response)
}

public func delete() async throws -> (AnalyticsRuleSchema?, URLResponse?) {
let (data, response) = try await self.apiCall.delete(endPoint: endpointPath())
if let result = data {
Expand All @@ -31,7 +34,7 @@ public struct AnalyticsRule {
}
return (nil, response)
}

private func endpointPath() -> String {
return "\(AnalyticsRules.resourcePath)/\(name)"
}
Expand Down
14 changes: 9 additions & 5 deletions Sources/Typesense/AnalyticsRules.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif


public struct AnalyticsRules {
private var apiCall: ApiCall
static var resourcePath: String = "\(Analytics.resourcePath)/rules"

init(apiCall: ApiCall) {
self.apiCall = apiCall
}

func upsert(params: AnalyticsRuleSchema) async throws -> (AnalyticsRuleSchema?, URLResponse?) {
let ruleData = try encoder.encode(params)
let (data, response) = try await self.apiCall.put(endPoint: endpointPath(params.name), body: ruleData)
Expand All @@ -18,17 +22,17 @@ public struct AnalyticsRules {

return (nil, response)
}

func retrieveAll() async throws -> (AnalyticsRulesRetrieveSchema?, URLResponse?) {
let (data, response) = try await self.apiCall.get(endPoint: endpointPath())
if let result = data {
let rules = try decoder.decode(AnalyticsRulesRetrieveSchema.self, from: result)
return (rules, response)
}

return (nil, response)
}

private func endpointPath(_ operation: String? = nil) -> String {
if let operation = operation {
return "\(AnalyticsRules.resourcePath)/\(operation)"
Expand Down
Loading

0 comments on commit ac11f7a

Please sign in to comment.