Переглянути джерело

[doc2] Add search_documents endpoint at /desktop/api2/docs/search

Returns the directories and documents based on given params that are accessible by the current user

Optional params:
    get_shared=<bool> - Controls whether to retrieve shared docs. Defaults to true.
    get_history=<bool> - Controls whether to retrieve history docs. Defaults to false.
    flatten=<bool>    - Controls whether to return documents in a flat list, or roll up documents to a common directory
                        if possible. Defaults to true.
    page=<n>          - Controls pagination. Defaults to 1.
    limit=<n>         - Controls limit per page. Defaults to all.
    type=<type>       - Show documents of given type(s) (directory, query-hive, query-impala, query-mysql, etc).
                        Defaults to all.
    sort=<key>        - Sort by the attribute <key>, which is one of: "name", "type", "owner", "last_modified"
                        Accepts the form "-last_modified", which sorts in descending order.
                        Defaults to "-last_modified".
    text=<frag>       - Search for fragment "frag" in names and descriptions.
Jenny Kim 9 роки тому
батько
коміт
6bfc61e

+ 57 - 5
desktop/core/src/desktop/api2.py

@@ -109,6 +109,8 @@ def get_shared_documents(request):
   """
   Returns the directories and documents that are shared with the current user, grouped by top-level directory.
   Optional params:
+    flatten=<bool>    - Controls whether to return documents in a flat list, or roll up documents to a common directory
+                        if possible. Defaults to false.
     page=<n>    - Controls pagination. Defaults to 1.
     limit=<n>   - Controls limit per page. Defaults to all.
     type=<type> - Show documents of given type(s) (directory, query-hive, query-impala, query-mysql, etc). Default to all.
@@ -123,10 +125,56 @@ def get_shared_documents(request):
     'documents': []
   }
 
-  documents = Document2.objects.get_shared_documents(request.user, flatten=False)
+  flatten = json.loads(request.GET.get('flatten', 'false'))
+
+  documents = Document2.objects.get_shared_documents(request.user)
+
+  # Refine results
+  response.update(_filter_documents(request, queryset=documents, flatten=flatten))
+
+  # Paginate
+  response.update(_paginate(request, queryset=response['documents']))
+
+  # Serialize results
+  if response['documents'] and response['documents'].count() > 0:
+    response['documents'] = [doc.to_dict() for doc in response['documents']]
+  else:
+    response['documents'] = []
+
+  return JsonResponse(response)
+
+
+@api_error_handler
+def search_documents(request):
+  """
+  Returns the directories and documents based on given params that are accessible by the current user
+  Optional params:
+    get_shared=<bool> - Controls whether to retrieve shared docs. Defaults to true.
+    get_history=<bool> - Controls whether to retrieve history docs. Defaults to false.
+    flatten=<bool>    - Controls whether to return documents in a flat list, or roll up documents to a common directory
+                        if possible. Defaults to true.
+    page=<n>          - Controls pagination. Defaults to 1.
+    limit=<n>         - Controls limit per page. Defaults to all.
+    type=<type>       - Show documents of given type(s) (directory, query-hive, query-impala, query-mysql, etc).
+                        Defaults to all.
+    sort=<key>        - Sort by the attribute <key>, which is one of: "name", "type", "owner", "last_modified"
+                        Accepts the form "-last_modified", which sorts in descending order.
+                        Defaults to "-last_modified".
+    text=<frag>       - Search for fragment "frag" in names and descriptions.
+  """
+
+  response = {
+    'documents': []
+  }
+
+  get_shared = json.loads(request.GET.get('get_shared', 'true'))
+  get_history = json.loads(request.GET.get('get_history', 'false'))
+  flatten = json.loads(request.GET.get('flatten', 'true'))
+
+  documents = Document2.objects.documents(user=request.user, get_shared=get_shared, get_history=get_history)
 
   # Refine results
-  response.update(_filter_documents(request, queryset=documents))
+  response.update(_filter_documents(request, queryset=documents, flatten=flatten))
 
   # Paginate
   response.update(_paginate(request, queryset=response['documents']))
@@ -140,6 +188,7 @@ def get_shared_documents(request):
   return JsonResponse(response)
 
 
+
 @api_error_handler
 def get_document(request):
   if request.GET.get('id'):
@@ -352,13 +401,13 @@ def import_documents(request):
     return JsonResponse({'message': stdout.getvalue()})
 
 
-def _filter_documents(request, queryset):
+def _filter_documents(request, queryset, flatten=True):
   """
   Given optional querystring params extracted from the request, filter the given queryset of documents and return a
     dictionary with the refined queryset and filter params
   :param request: request object with params
   :param queryset: Document2 queryset
-  :param key: name for key of refined document set
+  :param flatten: Return all results in a flat list if true, otherwise roll up to common directory
   """
   type_filters = request.GET.getlist('type', None)
   sort = request.GET.get('sort', '-last_modified')
@@ -370,6 +419,10 @@ def _filter_documents(request, queryset):
       search_text=search_text,
       order_by=sort)
 
+  # Roll up documents to common directory
+  if not flatten:
+    documents = documents.exclude(parent_directory__in=documents)
+
   count = documents.count()
 
   return {
@@ -387,7 +440,6 @@ def _paginate(request, queryset):
     and limit, and return the updated queryset along with pagination params used.
   :param request: request object with params
   :param queryset: queryset
-  :param key: name for key of refined document set
   """
   page = int(request.GET.get('page', 1))
   limit = int(request.GET.get('limit', 0))

+ 14 - 9
desktop/core/src/desktop/models.py

@@ -759,31 +759,36 @@ class Document2Manager(models.Manager):
   def document(self, user, doc_id):
     return self.documents(user).get(id=doc_id)
 
-  def documents(self, user):
+  def documents(self, user, get_shared=True, get_history=False):
     """
     Returns all documents that are either owned or shared with the user
     WARNING: Do NOT use this if you ONLY need documents that are owned by the user!
     """
-    return Document2.objects.filter(
+    if get_shared:
+      docs = Document2.objects.filter(
         Q(owner=user) |
         Q(document2permission__users=user) |
         Q(document2permission__groups__in=user.groups.all())
-    ).distinct().order_by('-last_modified')
+      )
+    else:
+      docs = Document2.objects.filter(owner=user)
+
+    if not get_history:
+      docs = docs.exclude(is_history=True)
 
-  def get_shared_documents(self, user, flatten=False):
+    docs = docs.distinct()
+
+    return docs.order_by('-last_modified')
+
+  def get_shared_documents(self, user):
     """
     Returns all documents that are shared with the user
-    :param flatten: True to return all directories and documents in a flat list,
-                    False to filter the documents to top-level directories
     """
     documents = Document2.objects.filter(
         Q(document2permission__users=user) |
         Q(document2permission__groups__in=user.groups.all())
     ).distinct()
 
-    if not flatten:
-      documents = documents.exclude(parent_directory__in=documents)
-
     return documents
 
   def refine_documents(self, documents, types=None, search_text=None, order_by=None):

+ 24 - 0
desktop/core/src/desktop/tests_doc2.py

@@ -628,3 +628,27 @@ class TestDocument2Permissions(object):
     response = self.client_not_me.get('/desktop/api2/doc/get', {'uuid': doc2.uuid})
     data = json.loads(response.content)
     assert_equal(doc2.uuid, data['uuid'], data)
+
+
+  def test_search_documents(self):
+    owned_dir = Directory.objects.create(name='test_dir', owner=self.user, parent_directory=self.home_dir)
+    owned_query = Document2.objects.create(name='query1.sql', type='query-hive', owner=self.user, data={}, parent_directory=owned_dir)
+    owned_workflow = Document2.objects.create(name='test.wf', type='oozie-workflow2', owner=self.user, data={}, parent_directory=owned_dir)
+
+    other_home_dir = Document2.objects.get_home_directory(user=self.user_not_me)
+    not_shared = Document2.objects.create(name='other_query1.sql', type='query-hive', owner=self.user_not_me, data={}, parent_directory=other_home_dir)
+    shared_1 = Document2.objects.create(name='other_query2.sql', type='query-hive', owner=self.user_not_me, data={}, parent_directory=other_home_dir)
+    shared_2 = Document2.objects.create(name='other_query3.sql', type='query-hive', owner=self.user_not_me, data={}, parent_directory=other_home_dir)
+
+    shared_1.share(user=self.user_not_me, name='read', users=[self.user], groups=[])
+    shared_2.share(user=self.user_not_me, name='read', users=[], groups=[self.default_group])
+
+    # 3 total docs (1 owned, 2 shared)
+    response = self.client.get('/desktop/api2/docs/search', {'type': 'query-hive'})
+    data = json.loads(response.content)
+    assert_true('documents' in data)
+    assert_equal(3, data['count'])
+    doc_names = [doc['name'] for doc in data['documents']]
+    assert_true('query1.sql' in doc_names)
+    assert_true('other_query2.sql' in doc_names)
+    assert_true('other_query3.sql' in doc_names)

+ 1 - 0
desktop/core/src/desktop/urls.py

@@ -118,6 +118,7 @@ dynamic_patterns += patterns('desktop.api',
 dynamic_patterns += patterns('desktop.api2',
   (r'^desktop/api2/docs/?$', 'get_documents'),
   (r'^desktop/api2/docs/shared?$', 'get_shared_documents'),
+  (r'^desktop/api2/docs/search?$', 'search_documents'),
 
   (r'^desktop/api2/doc/get$', 'get_document'),
   (r'^desktop/api2/doc/move$', 'move_document'),