def _search(self, query, search_term):
        criterias = mongoengine.Q()
        rel_criterias = mongoengine.Q()
        terms = shlex.split(search_term)
        if len(terms) == 1 and re.match(RE_OBJECTID, terms[0]):
            q = query.filter(id=bson.ObjectId(terms[0]))
            if q.count() == 1:
                return q
        for term in terms:
            op, term = parse_like_term(term)
            if op == 'contains':
                op = 'icontains'
            criteria = mongoengine.Q()
            for field in self._search_fields:
                if isinstance(field, mongoengine.fields.ReferenceField):
                    rel_model = field.document_type
                    rel_fields = (
                        getattr(self, 'column_searchable_refs', {})
                        .get(field.name, {})
                        .get('fields', ['id'])
                    )
                    if rel_fields == ['id'] and not re.match(RE_OBJECTID, term):
                        continue
                    ids = [
                        o.id for o in search_relative_field(rel_model, rel_fields, term)
                    ]
                    rel_criterias |= mongoengine.Q(**{'%s__in' % field.name: ids})
                elif isinstance(field, mongoengine.fields.ListField):
                    if not isinstance(field.field, mongoengine.fields.ReferenceField):
                        continue
                    rel_model = field.field.document_type_obj
                    rel_fields = (
                        getattr(self, 'column_searchable_refs', {})
                        .get(field.name, {})
                        .get('fields', 'id')
                    )
                    ids = [
                        o.id for o in search_relative_field(rel_model, rel_fields, term)
                    ]
                    rel_criterias |= mongoengine.Q(**{'%s__in' % field.name: ids})
                else:
                    flt = {'%s__%s' % (field.name, op): term}
                    q = mongoengine.Q(**flt)
                    criteria |= q
            criterias &= criteria
        return query.filter(criterias | rel_criterias)