Fluent-Search
Fluent-Search copied to clipboard
More predictable web search results
I'm migrating from Launchy to Fluent and I have around 200 web search entries. When I try to search for any entry in web search it always lists first 15 of entries from web settings. It looks like it doesn't filter them based on what I write in search input.
In Launchy this works great because searching is looking for matching words and can filter entries very efficiently. Is it possible to have something similiar in fluenty?
Hey @razjel, to filter results in Fluent Search you use Search Tags
. Web search will create tags automatically for your web searches, and you can decide the tag using the Tag
column in web searches -
To use a search tag, simply start typing it's name and press TAB
-
In addition, to make the behavior a bit more like Launchy, you can use Keyword mode
in Settings -> Search tags, that will let you search using tags without pressing TAB
, so if your tag is for Google is g
, then you can do g my search
to search in Google -
Let me know if it helps.
I already have tags defined. Inside main input indeed it suggests me most matching entry but it only suggests first one. In situation when I have similiar ones I can't easily see them like in launchy, f.e. in fluent I see only rpg advanced names
in launchy I see all options and can switch easily between them using down and up.
I set keyword mode in Search tags
options but it doesn't change way search behaves. I even restarted fluenty :<
Here are my options:
This issue has been potentially fixed in version 0.9.92.36 . Changelog - https://install.appcenter.ms/users/adirh3-gmail.com/apps/fluent-search-alpha/distribution_groups/exe
I really appreciate you found time to touch my issue :)
I tested it. It's much better but Launchy still handles it better for my use cases. With this version Fluent matches beginnings of tags to input from search field, but it only matches whole words and it looks like it can't skip words in between. Launchy allows to seek in any words and matching fragments of words.
Also I don't know if it's a bug, but it worked with fresh entries I added for the purpose of test but after I edited one of them it stopped being found. I don't know if it's because of fact I edited it or it's data is somehow causing Fluent to skip it.
@razjel thanks for the input! If you match part of a word, how would you know if that's what the user intended to search or it's part of a tag? I tried implementing it that way at the beginning, but it seems very confusing for me.
I think I do not fully understand the use cases here. TBH I never used Launchy and I don't really understand what I am seeing in that screenshot (sorry). I would appreciate it if you could describe what the use cases are with examples of input/output.
It's hard to describe with with words so I've written example implementation in JS. Launchy is doing a bit more with this, because it remembers which option you were choosing previously for given query and moves those entries to higher positions in final result.
function inteligentSearch(query, entries) {
let filteredEntries = entries.map((text) => {
return {text: text, lastIdx: -1, allFoundedIndexes: []};
});
const lowerCaseQuery = query.toLowerCase();
for (let i = 0; i < lowerCaseQuery.length; i++) {
const queryChar = lowerCaseQuery.charAt(i);
filteredEntries = filteredEntries.map((entry) => {
if (entry.text.charAt(entry.lastIdx + 1).toLowerCase() === queryChar) {
const resultIdx = entry.lastIdx + 1;
return {
text: entry.text,
lastIdx: resultIdx,
allFoundedIndexes: entry.allFoundedIndexes.concat(resultIdx),
};
} else {
const furtherText = entry.text.substring(entry.lastIdx + 1);
const foundIdx = furtherText.toLowerCase().search(queryChar);
if (foundIdx !== -1) {
const resultIdx = foundIdx + entry.lastIdx + 1;
return {
text: entry.text,
lastIdx: resultIdx,
allFoundedIndexes: entry.allFoundedIndexes.concat(resultIdx),
};
}
}
});
filteredEntries = filteredEntries.filter((entry) => {
return !!entry;
});
}
return filteredEntries;
}
function test(query, entries, expected) {
const result = inteligentSearch(query, entries);
try {
if (result.length !== expected.length) {
throw 1;
}
for (let i = 0; i < result.length; i++) {
if (result[i].text !== expected[i].text) {
throw 1;
}
if (JSON.stringify(result[i].allFoundedIndexes) !== JSON.stringify(expected[i].allFoundedIndexes)) {
throw 1;
}
}
console.log("succes");
} catch (error) {
console.log("failed: \n" + JSON.stringify(result) + "\n" + JSON.stringify(expected));
}
}
test(
"rpro",
["rpg roll20 net", "rpg spell roam"],
[
{text: "rpg roll20 net", allFoundedIndexes: [0, 1, 4, 5]},
{
text: "rpg spell roam",
allFoundedIndexes: [0, 1, 10, 11],
},
]
);
test("rprol", ["rpg roll20 net", "rpg spell roam"], [{text: "rpg roll20 net", allFoundedIndexes: [0, 1, 4, 5, 6]}]);