Realize /api/v0.1/ci_relations/s [done]

This commit is contained in:
pycook
2019-11-21 18:21:03 +08:00
parent bc7b51c544
commit 31a97d7ad0
24 changed files with 451 additions and 229 deletions

View File

@@ -1,3 +1,11 @@
# -*- coding:utf-8 -*-
__all__ = ['db', 'es']
__all__ = ['ci', 'ci_relation', 'SearchError']
class SearchError(Exception):
def __init__(self, v):
self.v = v
def __str__(self):
return self.v

View File

@@ -0,0 +1,3 @@
# -*- coding:utf-8 -*-
__all__ = ['db', 'es']

View File

@@ -12,25 +12,25 @@ from api.lib.cmdb.cache import AttributeCache
from api.lib.cmdb.cache import CITypeCache
from api.lib.cmdb.ci import CIManager
from api.lib.cmdb.const import RetKey
from api.lib.cmdb.const import TableMap
from api.lib.cmdb.search.db.query_sql import FACET_QUERY
from api.lib.cmdb.search.db.query_sql import QUERY_CI_BY_ATTR_NAME
from api.lib.cmdb.search.db.query_sql import QUERY_CI_BY_TYPE
from api.lib.cmdb.const import ValueTypeEnum
from api.lib.cmdb.search import SearchError
from api.lib.cmdb.search.ci.db.query_sql import FACET_QUERY
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_ATTR_NAME
from api.lib.cmdb.search.ci.db.query_sql import QUERY_CI_BY_TYPE
from api.lib.cmdb.utils import TableMap
from api.lib.utils import handle_arg_list
from api.models.cmdb import Attribute
from api.models.cmdb import CI
class SearchError(Exception):
def __init__(self, v):
self.v = v
def __str__(self):
return self.v
class Search(object):
def __init__(self, query=None, fl=None, facet_field=None, page=1, ret_key=RetKey.NAME, count=1, sort=None):
def __init__(self, query=None,
fl=None,
facet_field=None,
page=1,
ret_key=RetKey.NAME,
count=1,
sort=None,
ci_ids=None):
self.orig_query = query
self.fl = fl
self.facet_field = facet_field
@@ -38,6 +38,7 @@ class Search(object):
self.ret_key = ret_key
self.count = count
self.sort = sort
self.ci_ids = ci_ids or []
self.query_sql = ""
self.type_id_list = []
self.only_type_query = False
@@ -60,10 +61,10 @@ class Search(object):
operator, key = self._operator_proc(key)
if key in ('ci_type', 'type', '_type'):
return '_type', Attribute.TEXT, operator, None
return '_type', ValueTypeEnum.TEXT, operator, None
if key in ('id', 'ci_id', '_id'):
return '_id', Attribute.TEXT, operator, None
return '_id', ValueTypeEnum.TEXT, operator, None
attr = AttributeCache.get(key)
if attr:
@@ -286,6 +287,13 @@ class Search(object):
alias += "AA"
return None, query_sql
def _filter_ids(self, query_sql):
if self.ci_ids:
return "SELECT * FROM ({0}) AS IN_QUERY WHERE IN_QUERY.ci_id in ({1})".format(
query_sql, ",".join(list(map(str, self.ci_ids))))
return query_sql
def _query_build_raw(self):
queries = handle_arg_list(self.orig_query)
@@ -298,6 +306,7 @@ class Search(object):
s = time.time()
if query_sql:
query_sql = self._filter_ids(query_sql)
self.query_sql = query_sql
current_app.logger.debug(query_sql)
numfound, res = self._execute_sql(query_sql)

View File

@@ -8,20 +8,20 @@ from flask import current_app
from api.extensions import es
from api.lib.cmdb.cache import AttributeCache
from api.lib.cmdb.const import RetKey
from api.lib.cmdb.const import ValueTypeEnum
from api.lib.cmdb.search import SearchError
from api.lib.utils import handle_arg_list
from api.models.cmdb import Attribute
class SearchError(Exception):
def __init__(self, v):
self.v = v
def __str__(self):
return self.v
class Search(object):
def __init__(self, query=None, fl=None, facet_field=None, page=1, ret_key=RetKey.NAME, count=1, sort=None):
def __init__(self, query=None,
fl=None,
facet_field=None,
page=1,
ret_key=RetKey.NAME,
count=1,
sort=None,
ci_ids=None):
self.orig_query = query
self.fl = fl
self.facet_field = facet_field
@@ -29,6 +29,7 @@ class Search(object):
self.ret_key = ret_key
self.count = count or current_app.config.get("DEFAULT_PAGE_COUNT")
self.sort = sort or "ci_id"
self.ci_ids = ci_ids or []
self.query = dict(query=dict(bool=dict(should=[], must=[], must_not=[])))
@@ -58,10 +59,10 @@ class Search(object):
operator, key = self._operator_proc(key)
if key in ('ci_type', 'type', '_type'):
return 'ci_type', Attribute.TEXT, operator
return 'ci_type', ValueTypeEnum.TEXT, operator
if key in ('id', 'ci_id', '_id'):
return 'ci_id', Attribute.TEXT, operator
return 'ci_id', ValueTypeEnum.TEXT, operator
attr = AttributeCache.get(key)
if attr:
@@ -79,6 +80,10 @@ class Search(object):
}
})
def _filter_ids(self):
if self.ci_ids:
self.query['query']['bool'].update(dict(filter=dict(terms=dict(ci_id=self.ci_ids))))
@staticmethod
def _digit(s):
if s.isdigit():
@@ -171,6 +176,8 @@ class Search(object):
self._facet_build()
self._filter_ids()
return es.read(self.query, filter_path=filter_path)
def _facet_build(self):
@@ -183,7 +190,7 @@ class Search(object):
field: {
"terms": {
"field": "{0}.keyword".format(field)
if attr.value_type not in (Attribute.INT, Attribute.FLOAT) else field
if attr.value_type not in (ValueTypeEnum.INT, ValueTypeEnum.FLOAT) else field
}
}
})
@@ -212,7 +219,7 @@ class Search(object):
raise SearchError("Sort by <{0}> does not exist".format(field))
sort_by = "{0}.keyword".format(field) \
if attr.value_type not in (Attribute.INT, Attribute.FLOAT) else field
if attr.value_type not in (ValueTypeEnum.INT, ValueTypeEnum.FLOAT) else field
sorts.append({sort_by: {"order": sort_type}})
self.query.update(dict(sort=sorts))

View File

@@ -0,0 +1 @@
# -*- coding:utf-8 -*-

View File

@@ -0,0 +1,56 @@
# -*- coding:utf-8 -*-
import json
from flask import abort
from flask import current_app
from api.extensions import rd
from api.lib.cmdb.ci_type import CITypeRelationManager
from api.lib.cmdb.const import REDIS_PREFIX_CI_RELATION
from api.lib.cmdb.search.ci.db.search import Search as SearchFromDB
from api.lib.cmdb.search.ci.es.search import Search as SearchFromES
from api.models.cmdb import CI
class Search(object):
def __init__(self, root_id, level=1, query=None, fl=None, facet_field=None, page=1, count=None, sort=None):
self.orig_query = query
self.fl = fl
self.facet_field = facet_field
self.page = page
self.count = count or current_app.config.get("DEFAULT_PAGE_COUNT")
self.sort = sort or ("ci_id" if current_app.config.get("USE_ES") else None)
self.root_id = root_id
self.level = int(level)
def search(self):
ci = CI.get_by_id(self.root_id) or abort(404, "CI <{0}> does not exist".format(self.root_id))
ids = [self.root_id]
for _ in range(0, self.level):
_tmp = list(map(json.loads, filter(lambda x: x is not None, rd.get(ids, REDIS_PREFIX_CI_RELATION))))
ids = [j for i in _tmp for j in i]
if not self.orig_query or ("_type:" not in self.orig_query
and "type_id:" not in self.orig_query
and "ci_type:" not in self.orig_query):
type_ids = CITypeRelationManager.get_child_type_ids(ci.type_id, self.level)
self.orig_query = "_type:({0}),{1}".format(";".join(list(map(str, type_ids))), self.orig_query)
if current_app.config.get("USE_ES"):
return SearchFromES(self.orig_query,
fl=self.fl,
facet_field=self.facet_field,
page=self.page,
count=self.count,
sort=self.sort,
ci_ids=ids).search()
else:
return SearchFromDB(self.orig_query,
fl=self.fl,
facet_field=self.facet_field,
page=self.page,
count=self.count,
sort=self.sort,
ci_ids=ids).search()