docs: def search(self, *arg, **kw):
      """A full search function. This allows you to search expression
      using the following arguments.
  
      Arg:
          query (str): The search string expression.
  
      Optional Args:
          - include_entity (bool): include in each result the entity values associated of the fields stored.
          - add_wildcards (bool): set it if you want to consider matches that have prefix or suffixes the query.
          - something (bool): set `add_willcards` in case of none results for the query.
          - fields (list): specified the fields names that you want to consider.
          - except_fields (list): specified the fields names to not consider in the search.
          - models (list): a list of name of model to search or even the models from the database.
  
      Returns:
          (dict): A python dictionary with the results.
      """
      output = {
          'cant_results'  : 0
        , 'matched_terms' : defaultdict(set)
        , 'results'       : {}
        , 'runtime'       : 0
      }
  
      indexes = self.indexes()
  
      models = kw.get('models', list(self._entities.values()))
      if sys.version_info[0] < 3:
        models = [self._entities.get(model, None) if isinstance(model, str)
          or isinstance(model, unicode) else model for model in models]
        models = filter(lambda x: x is not None, models)
      else:
        models = [self._entities.get(model, None) if isinstance(model, str)
          or isinstance(model, str) else model for model in models]
        models = [x for x in models if x is not None]
  
  
      if models == [] or not models:
        models = list(self._entities.values())
  
      if self.debug:
        print("SEARCHING ON MODELS -> ", models)
  
      indexes = [m._pw_index_ for m in models if hasattr(m, '_pw_index_')]
  
      if indexes == []:
        return output
  
      runtime, cant = 0, 0
      ma            = defaultdict(set)
  
      for index in indexes:
        res     = index.search(*arg, **kw)
        runtime += res['runtime']
        cant    += res['cant_results']
        if res['cant_results'] > 0:
          output['results'][index._name] = {
              'items'         : res['results']
            , 'matched_terms' : res['matched_terms']
          }
          for k, ts in list(res['matched_terms'].items()):
            for t in ts:
              ma[k].add(t)
  
      output['cant_results']  = cant
      output['matched_terms'] = {k: list(v) for k, v in list(ma.items())}
      output['runtime']       = runtime
      return output