mirror of https://github.com/veops/cmdb.git
144 lines
6.0 KiB
Python
144 lines
6.0 KiB
Python
# -*- coding:utf-8 -*-
|
|
|
|
|
|
import json
|
|
from collections import Counter
|
|
|
|
from flask import abort
|
|
from flask import current_app
|
|
|
|
from api.extensions import rd
|
|
from api.lib.cmdb.ci import CIRelationManager
|
|
from api.lib.cmdb.ci_type import CITypeRelationManager
|
|
from api.lib.cmdb.const import REDIS_PREFIX_CI_RELATION
|
|
from api.lib.cmdb.resp_format import ErrFormat
|
|
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=None,
|
|
query=None,
|
|
fl=None,
|
|
facet_field=None,
|
|
page=1,
|
|
count=None,
|
|
sort=None,
|
|
reverse=False):
|
|
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 = level or 0
|
|
self.reverse = reverse
|
|
|
|
def _get_ids(self):
|
|
merge_ids = []
|
|
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
|
for level in range(1, sorted(self.level)[-1] + 1):
|
|
_tmp = list(map(lambda x: list(json.loads(x).keys()),
|
|
filter(lambda x: x is not None, rd.get(ids, REDIS_PREFIX_CI_RELATION) or [])))
|
|
ids = [j for i in _tmp for j in i]
|
|
if level in self.level:
|
|
merge_ids.extend(ids)
|
|
|
|
return merge_ids
|
|
|
|
def _get_reverse_ids(self):
|
|
merge_ids = []
|
|
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
|
for level in range(1, sorted(self.level)[-1] + 1):
|
|
ids = CIRelationManager.get_ancestor_ids(ids, 1)
|
|
if level in self.level:
|
|
merge_ids.extend(ids)
|
|
|
|
return merge_ids
|
|
|
|
def search(self):
|
|
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
|
cis = [CI.get_by_id(_id) or abort(404, ErrFormat.ci_not_found.format("id={}".format(_id))) for _id in ids]
|
|
|
|
merge_ids = self._get_ids() if not self.reverse else self._get_reverse_ids()
|
|
|
|
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 = []
|
|
for level in self.level:
|
|
for ci in cis:
|
|
if not self.reverse:
|
|
type_ids.extend(CITypeRelationManager.get_child_type_ids(ci.type_id, level))
|
|
else:
|
|
type_ids.extend(CITypeRelationManager.get_parent_type_ids(ci.type_id, level))
|
|
type_ids = list(set(type_ids))
|
|
if self.orig_query:
|
|
self.orig_query = "_type:({0}),{1}".format(";".join(list(map(str, type_ids))), self.orig_query)
|
|
else:
|
|
self.orig_query = "_type:({0})".format(";".join(list(map(str, type_ids))))
|
|
|
|
if not merge_ids:
|
|
# cis, counter, total, self.page, numfound, facet_
|
|
return [], {}, 0, self.page, 0, {}
|
|
|
|
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=merge_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=merge_ids).search()
|
|
|
|
def statistics(self, type_ids):
|
|
self.level = int(self.level)
|
|
_tmp = []
|
|
ids = [self.root_id] if not isinstance(self.root_id, list) else self.root_id
|
|
for lv in range(0, self.level):
|
|
if not lv:
|
|
if type_ids and lv == self.level - 1:
|
|
_tmp = list(map(lambda x: [i for i in x if i[1] in type_ids],
|
|
(map(lambda x: list(json.loads(x).items()),
|
|
[i or '{}' for i in rd.get(ids, REDIS_PREFIX_CI_RELATION) or []]))))
|
|
else:
|
|
_tmp = list(map(lambda x: list(json.loads(x).items()),
|
|
[i or '{}' for i in rd.get(ids, REDIS_PREFIX_CI_RELATION) or []]))
|
|
else:
|
|
for idx, item in enumerate(_tmp):
|
|
if item:
|
|
if type_ids and lv == self.level - 1:
|
|
__tmp = list(
|
|
map(lambda x: [(_id, type_id) for _id, type_id in json.loads(x).items()
|
|
if type_id in type_ids],
|
|
filter(lambda x: x is not None,
|
|
rd.get([i[0] for i in item], REDIS_PREFIX_CI_RELATION) or [])))
|
|
else:
|
|
|
|
__tmp = list(map(lambda x: list(json.loads(x).items()),
|
|
filter(lambda x: x is not None,
|
|
rd.get([i[0] for i in item], REDIS_PREFIX_CI_RELATION) or [])))
|
|
|
|
_tmp[idx] = [j for i in __tmp for j in i]
|
|
else:
|
|
_tmp[idx] = []
|
|
|
|
result = {str(_id): len(_tmp[idx]) for idx, _id in enumerate(ids)}
|
|
|
|
result.update(
|
|
detail={str(_id): dict(Counter([i[1] for i in _tmp[idx]]).items()) for idx, _id in enumerate(ids)})
|
|
|
|
return result
|