code: def add_index(collection,
                name,
                fields,
                transformer=None,
                unique=False,
                case_insensitive=False):
      
      assert len(name) > 0
      assert len(fields) > 0
      indexes = _db[collection].indexes
      index = indexes.setdefault(name, aadict())
      index.transformer = transformer
      index.value_map = {}  # json([value]) => set(object_id)
      index.unique = unique
      index.case_insensitive = case_insensitive
      index.fields = fields
      for obj in each_object(collection):
          _add_to_index(index, obj)
      _logger.info('added %s, %s index to collection %s on fields: %s',
          'unique' if unique else 'non-unique',
          'case-insensitive' if case_insensitive else 'case-sensitive',
          collection, ', '.join(fields))
docs: Add a secondary index for a collection ``collection`` on one or
      more ``fields``.
  
      The values at each of the ``fields`` are loaded from existing
      objects and their object ids added to the index.
  
      You can later iterate the objects of an index via
      ``each_indexed_object``.
  
      If you update an object and call ``save_object``, the index will
      be updated with the latest values from the updated object.
  
      If you delete an object via ``delete_object``, the object will
      be removed from any indexes on the object's collection.
  
      If a function is provided for ``transformer``, the values
      extracted from each object in the collection will be passed to
      the ``transformer``.  The ``transformer`` should return a list
      of values that will go into the index.
  
      If ``unique`` is true, then there may only be at most one object
      in the collection with a unique set of values for each the
      ``fields`` provided.
  
      If ``case_insensitive`` is true, then the value stored in the
      index will be lower-cased and comparisons thereto will be
      lower-cased as well.