{"id":18031767,"url":"https://github.com/dagronf/dfsearchkit","last_synced_at":"2025-03-27T05:30:58.410Z","repository":{"id":149491698,"uuid":"132298085","full_name":"dagronf/DFSearchKit","owner":"dagronf","description":"Swift/Objective-C framework for macOS around Apple's SearchKit","archived":false,"fork":false,"pushed_at":"2020-11-03T05:38:02.000Z","size":581,"stargazers_count":27,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T04:31:41.382Z","etag":null,"topics":["apple","macos","macosx","search","searchkit","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dagronf.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":"2018-05-06T01:46:58.000Z","updated_at":"2025-01-03T12:44:59.000Z","dependencies_parsed_at":"2023-05-17T02:45:42.708Z","dependency_job_id":null,"html_url":"https://github.com/dagronf/DFSearchKit","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/dagronf%2FDFSearchKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDFSearchKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDFSearchKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FDFSearchKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dagronf","download_url":"https://codeload.github.com/dagronf/DFSearchKit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245791341,"owners_count":20672665,"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":["apple","macos","macosx","search","searchkit","swift"],"created_at":"2024-10-30T10:10:43.147Z","updated_at":"2025-03-27T05:30:58.404Z","avatar_url":"https://github.com/dagronf.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DFSearchKit\n\nA framework implementing a search index and summary generator using SKSearchKit for both Swift and Objective-C\n\n![](https://img.shields.io/github/v/tag/dagronf/DFSearchKit) ![](https://img.shields.io/badge/macOS-10.11+-red) ![](https://img.shields.io/badge/Swift-5.0-orange.svg)\n![](https://img.shields.io/badge/License-MIT-lightgrey) [![](https://img.shields.io/badge/pod-compatible-informational)](https://cocoapods.org) [![](https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat)](https://swift.org/package-manager)\n\n## Why?\n\nI was interesting in learning about SKSearchKit and wanted a nice simple object to abstract away some of the unpleasantries when dealing with a C-style interface in Swift using native Swift types.\n\n## Usage\n\nThe base library is split into three classes and an async controller.\n\n### Copy\n\nCopy everything from the `DFSearchKit` sub-folder into your own project\n\n### Cocoapods\n\nAdd the following to your `Podfiles` file\n\n`pod 'DFSearchKit', :git =\u003e 'https://github.com/dagronf/DFSearchKit'`\n\n### Swift Package Manager\n\nImport via Xcode.\n\n## Classes\n\n### DFSearchIndex.Memory\n\nA class inheriting from DFSearchIndex that implements an in-memory index.  This index exists purely in memory, and will be destroyed when the index is deallocated.\n\n```swift\n// Create a new memory index using the default settings\nguard let indexer = DFSearchIndex.Memory() else {\n   assert(false)\n}\n\nindexer.add(textURL: \"doc-url://d1.txt\", text: \"This is my first document\")\n\t\nlet fileURL = // \u003cthe url for some file on disk\u003e\nindexer.add(fileURL, mimeType: \"application/pdf\")\n\n// ... add more documents\n\nindexer.flush()\n   \nlet searchresult = indexer.search(\"first\")\n\n// Do something with the search results\n\n```\n\n`DFSearchIndex.Memory` provides methods to get the raw index data for storing, and to load from data\n\n##### Load from a raw Data object\n```swift\nlet indexData = Data(...)\nguard let indexer = DFSearchIndex.Memory(data: indexData) else {\n   assert(false)\n}\n```\n\n##### Extract the raw Data object from the search index\n```swift\nlet newIndexData = indexer.data()\n```\n\n### DFSearchIndex.File\n\nA class inheriting from DFSearchIndex that allows the creation and use of an index on disk.\n\n```swift\n// Create a index on disk\nlet newFileURL = // \u003csome file url\u003e\nlet createProperties = DSFSearchIndex.CreateProperties() // search index properties\nguard let newIndex = DFSearchIndex.File(fileURL: newFileURL, properties: createProperties) else {\n   assert(false)\n}\n\n// Open a file index\nlet existingFileURL = // \u003csome file url\u003e\nguard let fileIndex = DFSearchIndex.File(fileURL: existingFileURL, writable: true) else {\n   assert(false)\n}\n\nlet documentURL = URL(string: (\"doc-url://d1.txt\")!\nfileIndex.add(documentURL, text: \"This is my first document\"))\n\t\nlet fileURL = // \u003cthe url for some file on disk\u003e\nfileIndex.add(fileURL, mimeType: \"application/pdf\")\n\n// Flush the index so that it is updated for searching\nfileIndex.flush()\n\n// Perform a basic search for the work 'first'\nvar result = indexer.search(\"first\")\n\nfileIndex.save()\nfileIndex.close()\n```\n\n### DFSearchIndex.AsyncController\n\n`DFSearchIndex.AsyncController` is a simple controller that takes an index object, and provides a safe method for handling async requests.\n\nFor example, to add a number of files asynchronously\n\n```swift\nguard let searchIndex = DFSearchIndex.Memory() else {\n   assert(false)\n}\n\nlet asyncController = DFSearchIndex.AsyncController(index: searchIndex, delegate: nil)\n\n// Create a file task containing the URLs to be indexed\nlet addTask = DFSearchIndex.AsyncController.FileTask(\u003cfile urls to add\u003e)\n\nasyncController.addURLs(async: addTask, complete: { task in\n    // \u003cblock that is executed when the files have been added to the index\u003e\n})\n\t\n...\n\n// Create a file task containing the URLs to be removed\n\nlet removeTask = DFSearchIndex.AsyncController.FileTask(\u003cfile urls to remove\u003e)\nasyncController.removeURLs(async: removeTask, complete: { task in\n\t// \u003cblock that is executed when the files have been removed from the index\u003e\n})\n\t\t\n```\nInternally the async controller uses an operation queue for handling requests.\n\n\n## Searching\n\nThere are two methods for search\n\n### Search all\n\nThe search all is available on the indexer object, and returns all the results it can get.  As such, for large indexes this may take quite a while to return.  It is provided mostly as a convenience function for small indexes.\n\n```swift\nguard let searchIndex = DFSearchIndex.Memory() else {\n   assert(false)\n}\n\n// Add some documents...\nsearchIndex.add(textURL: \"doc-url://d1.txt\", text: \"This is my first document\"))\n\n// Flush the index\nsearchIndex.flush()\n\n// Search for the word 'first'\nlet searchResult = indexer.search(\"first\")\n\t// searchResult.count == 1\n\t// searchResult[0].url == firstURL\n\t// searchResult[0].score == 1\n\nsearchIndex.save()\nsearchIndex.close()\n```\n\n### Progressive Search\n\nFor large indexes, the results may take quite a while to return.  Thus, the progressive index is more useful by returning limited sets of results progressively, and can be used on a background thread (as SKSearchIndex is thread safe) to progressively retrieve results in another thread (for example)\n\n```swift \n/// ... load documents ...\nlet search = indexer.progressiveSearch(query: \"dog\")\nvar hasMoreResults = true\nrepeat {\n   var searchChunk = search.next(10)\n   \n   // ... do something with searchChunk...\n   \n   hasMoreResults = searchChunk.moreResults\n}\nwhile hasMoreResults\n```\n\n## Summary Generation\n\nThe `DFSearchIndex.Summarizer` class provides a wrapper around the `SKSummary` interface, providing text rankings and orderings.\n\n```swift\nlet text = // \u003csome text\nlet summary = DFSummarizer(text)\n\n// Get the number of sentences in the text\nlet sentenceCount = summary.sentenceCount()\n\n// Get the number of paragraphs in the text\nlet paragraphCount = summary.paragraphCount()\n\n```\n\n## Samples\n\n* `SearchToy` is a (very!) basic UI to show integration\n* `dfsearchindex` is a simple command line tool (that is very unforgiving to its parameters at this point!) that uses DFSearchIndexFile to create a command line tool interface to the index\n\n## Tests\n\n* `DFSearchKitTests.swift`\n\n\tSwift tests.  Comprehensive\n\n* `DFSearchKitTests_objc.m` \n\n\tObjective-C tests, mainly for validating objc integration\n\n* `DFSearchIndexAsyncTests.swift`\n\n\tBasic test suite to validate the async controller aspect of the library\n\n* `DFSearchIndexSummaryTests.swift`\n\n\tBasic summary tests\n\n## Thanks\n\nMattt Thompson (NSHipster)\n\n[http://nshipster.com/search-kit/](http://nshipster.com/search-kit/)\n\nMarc Charbonneau\n\n[https://blog.mbcharbonneau.com/2009/02/26/searchkit-example-project/](https://blog.mbcharbonneau.com/2009/02/26/searchkit-example-project/)\n\nApple\n\n[https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/SearchKitConcepts/searchKit_concepts/searchKit_concepts.html](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/SearchKitConcepts/searchKit_concepts/searchKit_concepts.html)\n\nPhilip Dow (SPSearchStore)\n\n[https://github.com/phildow/SPSearchStore](https://github.com/phildow/SPSearchStore)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdfsearchkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdagronf%2Fdfsearchkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fdfsearchkit/lists"}