Search for Similar Notes from Obsidian Plugin

Enable searching for notes similar to the current note being viewed

## Main Changes
- 39a18e2 Extend search modal to search for similar notes
  - Hide input field on init, Trigger search on opening modal when in similar notes mode
  - Set input to contents of current markdown file and get notes similar to it
  - Re-rank, by default, when searching for similar notes
  - Filter out current note from similar note search results
- 0bed410 Only show `Find Similar Note' command in Editor
This commit is contained in:
Debanjum 2023-01-18 00:10:10 -03:00 committed by GitHub
commit b7fc344be1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 19 deletions

View file

@ -11,7 +11,8 @@
- [Setup Backend](#1-Setup-Backend)
- [Setup Plugin](#2-Setup-Plugin)
- [Use](#Use)
- [Query Filters](#Query-filters)
- [Search](#search)
- [Find Similar Notes](#find-similar-notes)
- [Upgrade](#Upgrade)
- [Upgrade Backend](#1-Upgrade-Backend)
- [Upgrade Plugin](#2-Upgrade-Plugin)
@ -56,7 +57,8 @@ pip install khoj-assistant && khoj --no-gui
See [official docs](https://help.obsidian.md/Advanced+topics/Community+plugins#Discover+and+install+community+plugins) for details
## Use
Click the *Khoj search* icon 🔎 on the [Ribbon](https://help.obsidian.md/User+interface/Workspace/Ribbon) or Search for *Khoj: Search* in the [Command Palette](https://help.obsidian.md/Plugins/Command+palette)
### Search
Click the *Khoj search* icon 🔎 on the [Ribbon](https://help.obsidian.md/User+interface/Workspace/Ribbon) or run *Khoj: Search* from the [Command Palette](https://help.obsidian.md/Plugins/Command+palette)
<details><summary>Query Filters</summary>
@ -80,6 +82,9 @@ Use structured query syntax to filter the natural language search results
</details>
### Find Similar Notes
To see other notes similar to the current one, run *Khoj: Find Similar Notes* from the [Command Palette](https://help.obsidian.md/Plugins/Command+palette)
## Upgrade
### 1. Upgrade Backend
```shell

View file

@ -10,7 +10,7 @@ export default class Khoj extends Plugin {
async onload() {
await this.loadSettings();
// Add a search command. It can be triggered from anywhere
// Add search command. It can be triggered from anywhere
this.addCommand({
id: 'search',
name: 'Search',
@ -21,21 +21,29 @@ export default class Khoj extends Plugin {
}
});
// Add similar notes command. It can only be triggered from the editor
this.addCommand({
id: 'similar',
name: 'Find Similar Notes',
editorCheckCallback: (checking) => {
if (!checking && this.settings.connectedToBackend)
new KhojModal(this.app, this.settings, true).open();
return this.settings.connectedToBackend;
}
});
// Create an icon in the left ribbon.
this.addRibbonIcon('search', 'Khoj', (_: MouseEvent) => {
// Called when the user clicks the icon.
this.settings.connectedToBackend
? new KhojModal(this.app, this.settings).open()
: new Notice(`Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings`);
? new KhojModal(this.app, this.settings).open()
: new Notice(`Ensure Khoj backend is running and Khoj URL is pointing to it in the plugin settings`);
});
// Add a settings tab so the user can configure khoj
this.addSettingTab(new KhojSettingTab(this.app, this));
}
onunload() {
}
async loadSettings() {
// Load khoj obsidian plugin settings
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());

View file

@ -9,10 +9,15 @@ export interface SearchResult {
export class KhojModal extends SuggestModal<SearchResult> {
setting: KhojSetting;
rerank: boolean = false;
find_similar_notes: boolean;
constructor(app: App, setting: KhojSetting) {
constructor(app: App, setting: KhojSetting, find_similar_notes: boolean = false) {
super(app);
this.setting = setting;
this.find_similar_notes = find_similar_notes;
// Hide input element in Similar Notes mode
this.inputEl.hidden = this.find_similar_notes;
// Register Modal Keybindings to Rerank Results
this.scope.register(['Mod'], 'Enter', async () => {
@ -49,20 +54,34 @@ export class KhojModal extends SuggestModal<SearchResult> {
this.setPlaceholder('Search with Khoj 🦅...');
}
async onOpen() {
if (this.find_similar_notes) {
// If markdown file is currently active
let file = this.app.workspace.getActiveFile();
if (file && file.extension === 'md') {
// Enable rerank of search results
this.rerank = true
// Set contents of active markdown file to input element
this.inputEl.value = await this.app.vault.read(file);
// Trigger search to get and render similar notes from khoj backend
this.inputEl.dispatchEvent(new Event('input'));
this.rerank = false
}
else {
this.resultContainerEl.setText('Cannot find similar notes for non-markdown files');
}
}
}
async getSuggestions(query: string): Promise<SearchResult[]> {
// Query Khoj backend for search results
let searchUrl = `${this.setting.khojUrl}/api/search?q=${query}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown`
let encodedQuery = encodeURIComponent(query);
let searchUrl = `${this.setting.khojUrl}/api/search?q=${encodedQuery}&n=${this.setting.resultsCount}&r=${this.rerank}&t=markdown`
let results = await request(searchUrl)
.then(response => JSON.parse(response))
.then(data => {
return data.map((result: any) => {
let processedResult: SearchResult = {
entry: result.entry,
file: result.additional.file
};
return processedResult;
})
});
.then(data => data
.filter((result: any) => !this.find_similar_notes || !result.additional.file.endsWith(this.app.workspace.getActiveFile()?.path))
.map((result: any) => { return { entry: result.entry, file: result.additional.file } as SearchResult; }));
return results;
}