Selaa lähdekoodia

HUE-3450 [metadata] Initial search_entities Navigator API endpoint

GET /metadata/api/navigator/search_entities?query_s=sample%20hue

Required params:
query_s: search query string with whitespace separated search terms

Optional:
offset: default 0
limit: default 100
Jenny Kim 9 vuotta sitten
vanhempi
commit
f8df374945

+ 26 - 0
desktop/libs/metadata/src/metadata/navigator_api.py

@@ -53,6 +53,32 @@ def error_handler(view_fn):
   return decorator
 
 
+@error_handler
+def search_entities(request):
+  response = {'status': -1}
+
+  api = NavigatorApi()
+  query_s = request.REQUEST.get('query_s')
+  offset = request.REQUEST.get('offset', 0)
+  limit = request.REQUEST.get('limit', 100)
+
+  if not query_s:
+    raise MetadataApiException("search_entities requires query_s search string")
+
+  entities = api.search_entities(query_s)
+
+  response = {
+    'entities': entities,
+    'count': len(entities),
+    'offset': offset,
+    'limit': limit,
+    'query_s': query_s,
+    'status': 0
+  }
+
+  return JsonResponse(response)
+
+
 @require_POST
 @error_handler
 def find_entity(request):

+ 38 - 0
desktop/libs/metadata/src/metadata/navigator_client.py

@@ -55,6 +55,44 @@ class NavigatorApi(object):
     self.__params = ()
 
 
+  def search_entities(self, query_s, limit=100, offset=0, **filters):
+    """
+    GET /api/v3/entities?query=()
+    http://cloudera.github.io/navigator/apidocs/v3/path__v3_entities.html
+    :param query_s: a query string of search terms (e.g. - sales quarterly);
+      Currently the search will perform an OR boolean search for all terms (split on whitespace), against a whitelist
+      of search_fields.
+      TODO: support smarter boolean searching with arbitrary ordering and precedence of conditionals
+    :param filters: TODO: IMPLEMENT ME, required to support property search
+    """
+    search_fields = ('originalName', 'originalDescription', 'name', 'description', 'tags')
+
+    try:
+      params = self.__params
+
+      search_terms = [term.lower() for term in query_s.strip().split()]
+
+      query_clauses = []
+      for term in search_terms:
+        query_clauses.append('OR'.join(['(%s:*%s*)' % (field, term) for field in search_fields]))
+
+      filter_query = 'OR'.join(['(%s)' % clause for clause in query_clauses])
+
+      params += (
+        ('query', filter_query),
+        ('offset', offset),
+        ('limit', limit),
+      )
+
+      response = self._root.get('entities', headers=self.__headers, params=params)
+
+      return response
+    except RestException, e:
+      msg = 'Failed to search for entities with search query: %s' % query_s
+      LOG.exception(msg)
+      raise NavigatorApiException(msg)
+
+
   def find_entity(self, source_type, type, name, **filters):
     """
     GET /api/v3/entities?query=((sourceType:<source_type>)AND(type:<type>)AND(originalName:<name>))

+ 5 - 0
desktop/libs/metadata/src/metadata/navigator_tests.py

@@ -57,6 +57,11 @@ class TestNavigatorApi(object):
     cls.user.save()
 
 
+  def test_search_entities(self):
+    # TODO: write me
+    pass
+
+
   def test_find_entity(self):
     entity = self.api.find_entity(source_type='HIVE', type='DATABASE', name='default')
     assert_true('identity' in entity, entity)

+ 1 - 0
desktop/libs/metadata/src/metadata/urls.py

@@ -20,6 +20,7 @@ from django.conf.urls import patterns, url
 
 # Navigator API
 urlpatterns = patterns('metadata.navigator_api',
+  url(r'^api/navigator/search_entities/?$', 'search_entities', name='search_entities'),
   url(r'^api/navigator/find_entity/?$', 'find_entity', name='find_entity'),
   url(r'^api/navigator/get_entity/?$', 'get_entity', name='get_entity'),
   url(r'^api/navigator/add_tags/?$', 'add_tags', name='add_tags'),