1

I have a collection of Bars, each of which have isar links to Foos:

@collection
class Bar{
  Id? id;
  
  final foos = IsarLinks<Foo>();
  ... // Bar stuff
};

Each Foo object has a field named text, which is a String:

@collection
class Foo{
  Id? id;
  
  late String text;
  ... // Foo stuff
};

Now, what I would like to do is search and find all the Foos linked to a particular Bar that contain all of the given key words in their text (preferably case insensitive). So, searching with the key words "canada" and "street" should match a Foo with text = "I don't know what street, Canada is on. - Al Capone

Isar has a guide on how to do a full text search. In it, they recommend adding an index of the words of the text searched on, like so:

@collection
class Foo{
  Id? id;
  
  late String text;
  
  @Index(type: IndexType.value, caseSensitive: false) // for more flexibility; see https://isar.dev/recipes/full_text_search.html#i-want-more-control
  List<String> get words => Isar.splitWords(text); // see https://isar.dev/recipes/full_text_search.html#splitting-text-the-right-way
};

However, there does not seem to be an easy way to filer based on an index with IsarLinks.

My questions:

  • Is there a way to filter based on an index through all the items of an IsarLinks object?
  • If not, what would be the best way to perform a text search like I described? As a bonus question, why can't I do this with IsarLinks?

Note: I know I can simply use IsarLinks.filter and build a query that selects all Foos with text containing all the key words, but I am wondering if there is a way to do a text search in the way Isar (with indexes) recommends on IsarLinks.

Captain Hatteras
  • 490
  • 3
  • 11

1 Answers1

1

Isar does not provide a direct way to filter based on an index through all the items of an IsarLinks object. The indexing functionality is primarily designed for individual properties of an object rather than for complex relationships like IsarLinks.

To perform a text search across the linked Foo objects based on the text field, you can follow these steps:

  1. Retrieve the linked Foo objects from the IsarLinks of a specific Bar.
  2. Filter the Foo objects based on the search keywords using the where method and a custom condition.
  3. Use a case-insensitive search condition to match the keywords in the text field.

Here's an example implementation of the text search functionality:

import 'package:isar/isar.dart';

@Collection()
class Bar {
  @Id()
  int? id;

  final foos = IsarLinks<Foo>();

  // ... Bar stuff
}

@Collection()
class Foo {
  @Id()
  int? id;

  late String text;

  // ... Foo stuff
}

void searchTextInFoos(Bar bar, List<String> keywords) {
  final foos = bar.foos;

  final searchResults = foos
      .where((foo) => keywords.every(
            (keyword) => foo.text.toLowerCase().contains(keyword.toLowerCase()),
          ))
      .toList();

  // Use the searchResults as needed
}

In this example, the searchTextInFoos function takes a Bar object and a list of search keywords as input. It filters the Foo objects linked to that Bar based on the keywords using the where method.

The where method applies a custom condition to each Foo object, checking if all keywords are contained within the text field. The condition uses a case-insensitive comparison by converting both the text and keyword to lowercase.

Finally, the search results are stored in the searchResults list, which you can utilize as needed.

While it would be convenient to perform a full-text search directly on an IsarLinks object with the help of indexing, the current version of Isar does not provide this capability. However, the approach outlined above allows you to achieve the desired text search functionality for the linked Foo objects.

Uniruddh
  • 4,427
  • 3
  • 52
  • 86