Trie - how can we search for a given value?

Hi, I’m looking for a way to find a special property in a trie structure. E.g: I have the following type in a Trie structure:

public type Article = {
artCategory: Text;
artName: Text;
artOwner: Text;
artText: Text;
};

and I would like to find all articles with the artCategory == “motoko” for example.

How can I do this?

I found a possible solution: I can use the method: filter

func filter<K, V>(t : Trie <K, V>, f : (K, V) → Bool) : Trie<K, V>

Can anybody show me an example how this function is used in the context of Trie ?

Something like:

let motokoArticles = Trie.filter<Key, Article>(t, func (k, v) { v.artCategory == "motoko" });  

or, if you don’t like specify the type parameters, but prefer to type the function argument:

let motokoArticles = Trie.filter(t, func (k  : Key, v : Article) : Bool { v.artCategory == "motoko" });  

should work.

If you then want to get at the key-value pair, for instance, to iterate over them, this function might be helpful.

https://sdk.dfinity.org/docs/base-libraries/trie#toArray

I haven’t used Trie much myself, but it looks like the API could use some more ways of enumerating the keys, values, and key-value pairs of a trie directly. I’ll file an issue.

4 Likes

Cool, thank you. Finally I come up with that function to query the category from my articles trie.

public query func getArticleByCategory (artCategory : Text) : async Trie.Trie<ArtId, Article>  {   
  let articleAsArray = Trie.filter<ArtId, Article>(articles, func (k, v) { v.artCategory == artCategory });  
     return articleAsArray;
     };
1 Like

Glad to hear it.

For the record, you should be able to simplify this to just:

    public query func getArticleByCategory (artCategory : Text) : async Trie.Trie<ArtId, Article>  {   
      Trie.filter<ArtId, Article>(articles, func (k, v) { v.artCategory == artCategory });  
    };

There’s no need to name the filtered trie; just implicitly return it as the last expression in the block/body of the function.

Thanks again, but on the syntax I have to get used to it first.

May a ask one further question. This function returns a leaf to the frontend javascript canister. Is there a library to convert that data structure to a better useable javascript array or object ?

Thanks in advanced.

Currently the javascript agent gives you types closely mapped to the candid IDL types, there has been discussion on the merits of this of course, a good approach is to create small utility functions in your project that handle conversions for you, this also allows you to maintain any future changes to the returned types in a central place, something similar to this: https://github.com/enzoh/superheroes/blob/master/src/www/utilities/idl.js

1 Like