The Keyword filter works very well in Workshop and now supports “All”, “Any”, and “Phrase” searches. I’ve been working on a hybrid search that searches for any space-separated string and all quoted words or phrases. Ultimately, the goal is to incorporate all the advanced search features here: https://www.google.com/advanced_search.
For now though, the below TypeScript searches space-separated words and all quoted text.
The only requirements from the backend are a unique, non-null PrimaryKey property and a search_property property that concatenates all properties into a single text string (with spaces).
import { Filters, Function } from "@foundry/functions-api"
import { ObjectSet, MyObjectType} from "@foundry/ontology-api";
export class MyFunctions {
@Function()
public async filter_text(objs : ObjectSet<MyObjectType>, str : string): Promise<ObjectSet<MyObjectType>> {
str = str.trim();
str = str.replace(/[^a-zA-Z0-9"\s]/g, ''); // Clean searches like 0:0, which throw a TooManyClauses error in Workshop
if (!str) { // Check for empty strings
return objs;
} else {
// Extract quoted phrases
const quoted_phrases_regex = /("[^"]*")/g;
const quoted_phrases = str.match(quoted_phrases_regex) || [];
let filtered_str = str;
for (const quoted_phrase of quoted_phrases) {
filtered_str = filtered_str.replace(quoted_phrase, "");
}
// Extract words not in quoted phrases
const regex = /(\S+)/g;
const unquoted_words = filtered_str.match(regex) || [];
// Initialize filteredObjs according to the presence of unquoted search terms
let filteredObjs; // Declare filteredObjs
if (unquoted_words.length === 0) {
filteredObjs = objs; // Initialize a complete set
} else {
filteredObjs = objs.filter(obj => Filters.not(obj.primaryKey_.hasProperty())); // Initialize an empty set
}
// Union searches with unquoted words (search any of these)
for (const word of unquoted_words) {
console.log(word)
filteredObjs = filteredObjs.union(objs.filter(obj => obj.search_property.phrasePrefix(word)));
}
// Intersect searches with quoted words or phrases (search all of these)
for (const phrase of quoted_phrases) {
console.log(phrase);
filteredObjs = filteredObjs.intersect(objs.filter(obj => obj.search_property.phrasePrefix(phrase)));
}
return filteredObjs;
}
}
}