나는 mongodb의 List 타입을 $in 으로 검색하려고 하는데..이게 지원안된다.
태그 같은건 ["한국", "여행"] 이런식으로 list 타입으로 관리되고, 해쉬태그처럼 사용하는거라 $in 검색을 하고 싶은데
(=성능상 contains 하면 데이터 많으면 힘들다)
관계형 데이터베이스에서는 이런 N개의 데이터는 없었기 때문일까? 기본적으로는 지원안된다.
column_searchable_list = ('tags', ) # Document 를 ListField(StringField()) 필드로 구성했다고 했을때...
이걸 하려면 ModelView를 고쳐서 쓰면 된다.
참고로 기존 코드만 배끼고 저 파란부분만 추가해서 오버라이딩 한거다.
이 모델뷰를 이용해 구성하면 list<stringField> 구성에 대해서는 $in 검색을 한다.
# -*- coding: utf-8 -*- import sys import mongoengine from flask_admin.contrib.mongoengine.tools import parse_like_term reload(sys) sys.setdefaultencoding('utf-8') from flask_admin.contrib.mongoengine import ModelView from flask_admin._compat import string_types from mongoengine import ListField
class CustomModelView(ModelView): """ list 타입 검사 안되는 문제를 해결 """ def init_search(self): if self.column_searchable_list: for p in self.column_searchable_list: if isinstance(p, string_types): p = self.model._fields.get(p) # convert type if p is None: raise Exception('Invalid search field') # list type (my code) if isinstance(p, ListField): p_sub = p.field if type(p_sub) in self.allowed_search_types: self._search_fields.append(p) continue field_type = type(p) if (field_type not in self.allowed_search_types): raise Exception('Can only search on text columns. ' + 'Failed to setup search for "%s"' % p) self._search_fields.append(p) return bool(self._search_fields) def _search(self, query, search_term): op, term = parse_like_term(search_term) criteria = None for field in self._search_fields: if isinstance(field, ListField): flt = {'%s__%s' % (field.name, 'in'): (term,)} else: flt = {'%s__%s' % (field.name, op): term} q = mongoengine.Q(**flt) if criteria is None: criteria = q else: criteria |= q
return query.filter(criteria)