Using Indexes


A new feature of WebWidgets is the ability to create indexes on tables. This page provides high-level documentation, please see the JS API docs for more specific information. These features are available in the open-core version of WWIO.

Creating an Index

There are two ways to create an index: and . Both of these methods take the same arguments: the tablename of the Widget table, and an fnamelist, which is short hand for "field name list". The former argument should be self-evident. The latter argument is a list of strings which correspond to column names of the table.

The basic method issues an error message if the index already exists (this is to help catch errors early). Thus, this method is appropriate for global scopes; you can call it once at the top of a page's JavaScript definitions, or in a shared, auto-included JS file. Note, however, that creating an index has some performance costs, so it is worth avoiding the index creation if it is not necessary. To help improve performance, there is an opportunistic method . This method first checks if the specified index already exists, and returns early if so.

Lookup Using an Index

An index is used to rapidly find records with certain field values. The index-based lookup is much faster than a naive table scan, and this speed improvement can be significant in some situations. To illustrate the benefit of an index, suppose we have a table with a day_code column, and we wish to find all of the records for a certain date.

        // Naive method - full table scan
        function naiveLookup(datestr)
        {
            return W.getItemList("day_plan_main").filter(item => item.getDayCode() == datestr);
        }

        // smart lookup - use the index
        function smartLookup(datestr)
        {
            return W.lookupFromIndex("day_plan_main", { "day_code" : datestr });
        }

The function takes a table name, and a hash that expresses the field values that are being searched for. The method returns a list; you should be careful to check if the list is empty before trying to read items from it. In the above smartLookup(...) method, it is assumed that the index has already been created elsewhere. If the index does not exist, this code will produce an error when called. To avoid this, we can use the opportunistic index creation method:

        // smart lookup, create index if absent
        function smartLookup(datestr)
        {
            W.createIndexIfAbsent("day_plan_main", ["day_code"]);
            return W.lookupFromIndex("day_plan_main", { "day_code" : datestr });
        }

There is a subtle rule about the relationship between the fields used in the index creation, and the fields used in the query. You are not required to use all the field names in the index when querying it. For example, this code would still work:

        function smartLookup(datestr)
        {
            W.createIndexIfAbsent("day_plan_main", ["day_code", "phase_id"]);
            return W.lookupFromIndex("day_plan_main", { "day_code" : datestr });
        }

Since day_code is the first field in the index definition, querying with only that column is fine. However, if you tried to query with only the second column, you would get an error:

        function smartLookupWontWork(phaseid)
        {
            W.createIndexIfAbsent("day_plan_main", ["day_code", "phase_id"]);
            return W.lookupFromIndex("day_plan_main", { "phase_id" : phaseid });
        }

Of course, if you really wanted to query against the phase_id column, you could just create another index on the table. Notice also that the order of the fields in the JS hash definition does not matter, the system will figure out how to query them in the right order. For example, this code will work fine:

        function smartLookupDouble(datestr, phaseid)
        {
            W.createIndexIfAbsent("day_plan_main", ["day_code", "phase_id"]);
            return W.lookupFromIndex("day_plan_main", { "phase_id" : phaseid, "day_code" : datestr });
        }

To find other examples of Index usage in the Gallery code, try this GitHub search.