docs: def _compile_query(self):
          """
          Builds SOLR query and stores it into self.compiled_query
          """
          # https://wiki.apache.org/solr/SolrQuerySyntax
          # http://lucene.apache.org/core/2_9_4/queryparsersyntax.html
          query = []
  
          # filtered_query = self._model_class.row_level_access(self._current_context, self)
          # if filtered_query is not None:
          #     self._solr_query += filtered_query._solr_query
          # print(self._solr_query)
          for key, val, is_escaped in self._solr_query:
              # querying on a linked model by model instance
              # it should be a Model, not a Node!
              if key == 'key':
                  key = '_yz_rk'
              elif key == '-key':
                      key = '-_yz_rk'
              elif key[:5] == 'key__':  # to handle key__in etc.
                  key = '_yz_rk__' + key[5:]
              elif key[:6] == '-key__':  # to handle key__in etc.
                  key = '-_yz_rk__' + key[6:]
  
              key, val, is_escaped = self._process_query_val(key, val, is_escaped)
              # if it's not one of the expected objects, it should be a string
              # if key == "OR_QRY" then join them with "OR" after escaping & parsing
              if key == 'OR_QRY':
                  key = 'NOKEY'
                  val = ' OR '.join(
                      ['%s:%s' % self._parse_query_key(*self._process_query_val(k, v, is_escaped)) for
                       k, v in val.items()])
                  is_escaped = True
              # __in query is same as OR_QRY but key stays same for all values
              elif key.endswith('__in'):
                  if not val:
                      raise ValueError("query value list can not be empty for __in query, "
                                       "please check if it is empty or not before execute filter.")
                  key = key[:-4]
                  val = ' OR '.join(
                      ['%s:%s' % (key, self._escape_query(v, is_escaped)) for v in val])
                  if key.startswith('-'):
                      val = '*:* %s' % val
                  key = 'NOKEY'
                  is_escaped = True
              # parse the query
              key, val = self._parse_query_key(key, val, is_escaped)
  
              # as long as not explicitly asked for,
              # we filter out records with deleted flag
              if key == 'deleted':
                  self.want_deleted = True
              # convert two underscores to dot notation
              key = key.replace('__', '.')
              # NOKEY means we already combined key partition in to "val"
              if key == 'NOKEY':
                  query.append("(%s)" % val)
              else:
                  query.append("%s:%s" % (key, val))
  
          # need to add *:* for negative queries, if
          # query has only one criteria, such as:
          # (-name:Jack) AND -deleted:True
          # this wont work properly, it must be altered as
          # (*:* -name:Jack) AND -deleted:True
          if len(query) == 1:
              q = query[0]
              if q.startswith('-'):
                  query[0] = '*:* %s' % q
              if q[:2] == '(-':
                  query[0] = '( *:* %s' % q[1:]
  
          # filter out "deleted" fields if not user explicitly asked for
  
          # join everything with "AND"
          joined_query = self._QUERY_GLUE.join(query)
          if not self.want_deleted:
              if joined_query:
                  joined_query = "(%s) AND -deleted:True" % joined_query
              else:
                  joined_query = '-deleted:True'
          elif not joined_query:
              joined_query = '*:*'
          self.compiled_query = joined_query