2016-12-15 3 views
0

В KeystoneJS мы в настоящее время используем агрегацию для запроса Mongo и просто захватываем весь набор и возвращаем это. Теперь, когда мы получаем больше данных, нам нужно разбивать на страницы. KeystoneJS поддерживает разбиение на страницы, но по внешнему виду он поддерживает только команду find в параметре параметра where. Есть ли способ, которым разбиение на страницы, предоставленное KeystoneJS, может разбивать на страницы результаты из запроса агрегации?KeystoneJS список разбивки на совокупность результатов

Пример агрегатных запросов:

keystone.list('Posts').model.aggregate([ 
{'$match': {"state":"published"}}, 
{'$unwind': {'path':"$actions", 'preserveNullAndEmptyArrays': false}}, 
     {'$lookup': { 
     'from':"actions", 
     'localField': "actions", 
     'foreignField': "_id", 
     'as': "actions"}}, 
     {'$match': {"actions.key": action}}, 
{'$unwind': {'path':"$postTopics"}}, 
     {'$lookup': { 
     'from':"posttopics", 
     'localField': "postTopics", 
     'foreignField': "_id", 
     'as': "posttopics"}}, 
     {'$match': {"posttopics.key": topic}}, 
{'$unwind': {'path':"$postSubTopics"}}, 
     {'$lookup': { 
     'from':"postsubtopics", 
     'localField': "postSubTopics", 
     'foreignField': "_id", 
     'as': "postsubtopics"}}, 
     {'$match': {"postsubtopics.key": subtopic}}, 
{'$unwind': 
    {'path':"$postSubTopics", 
    'preserveNullAndEmptyArrays': true}}, 
    {'$unwind': 
    {'path':"$postTopics", 
    'preserveNullAndEmptyArrays': true}}, 
    {'$lookup': { 
    'from':"postsubtopics", 
    'localField': "postSubTopics", 
    'foreignField': "_id", 
    'as': "postsubtopics"}}, 
    {'$lookup': { 
    'from':"posttopics", 
    'localField': "postTopics", 
    'foreignField': "_id", 
    'as': "posttopics"}}, 
    {'$match': { 
    '$or': 
     [ 
     { "postsubtopics.searchKeywords": keyword }, 
     { "posttopics.searchKeywords": keyword } 
     ] 
    }} 
]).sort('-publishedDate'); 

Результаты, которые возвращают обратно из этого я хотел бы иметь возможность постраничной через. Я изучаю использование мангуста, чтобы сделать это, или просто фильтровать через массив с помощью javascript, но так как я вижу, что у Keystone есть разбиение на страницы, я хотел спросить участников, если это поддерживается.

ответ

0

Во-первых, вы пробовали просто:

keystone.list('Posts').model.paginate({ 
       page: req.query.page || 1, 
       perPage: 10, 
       maxPages: 10, 
      }) 
      .aggregate([...]) 

Я не вижу причин, почему это не должно работать, хотя я не знаком с тем, как мангуст работ под капотом , Трапецеидальность, конечно же, позволяет вам делать так называемый pagination call.

В противном случае вы можете разделить это на два вызова. Сначала сделайте стандартный вызов на странице, чтобы получить идентификаторы сообщений на этой странице и сохраните их в массиве. Затем вы можете выполнить совокупный вызов, который сначала соответствует сообщениям, которые имеют идентификаторы в только что созданном массиве. Есть сообщение StackOverflow о том, как совместить, если значение находится в массиве here. Это должно достичь того, чего вы хотите?

И, наконец, вы уверены, что все, что агрегация и т.д. необходимо. Я не на 100% от того, что здесь достигается, поскольку я никогда не использовал агрегат, однако вы могли бы использовать postTopics в качестве поля отношений на этой должности, что позволит вам вместо этого называть populate? Точно так же каждая тема может иметь отношение к его подтемам и т. Д. И т. Д. Я предполагаю, что ваш случай использования слишком сложный для этого, но я думал, что упомянул об этом на всякий случай.

+0

Спасибо за ввод. Я попробовал ранее указанный выше запрос, а также попробовал много вариантов, но ни один из них не сработал. В приведенном выше примере жалуется, что агрегат не является функцией. У меня есть место, где я хватаю все данные и выполняю разбивку на страницы с помощью JS. Рамка агрегации в Монго, по-видимому, растет в популярности, и мне было просто любопытно, если бы была простая вставка и игра для трассировки трапецеидальных искажений, чтобы поддерживать агрегацию вместо поиска запросов. – lshaffer

0

Для тех, кто находит это позже, я смог использовать Mongoose, чтобы помочь очистить этот запрос. К сожалению, с помощью paginate пока не представляется возможным принять во внимание фильтрацию после заполнения. Paginate будет возвращать все сообщения, которые соответствуют предложению where, но это не помогает, если мне нужно больше фильтровать по заполняемым полям. К тому времени, как мы заполняем, разбиение на страницы уже сделано. Таким образом, если paginate возвращает 10 из 30 изначально, после того, как я сделаю фильтр в exec, я могу получить только 3 из 10. Я создал глобальный объект PostsPaginator, чтобы помочь мне с этим, вместо того, чтобы использовать paginate Keystone.

var populateObjects = [ 
     { 
     path: 'actions', 
     match: { 'key': action} 
     }, 
     { 
     path: 'postTopics', 
     match: { '$or': [ 
      {'key': topic}, 
      { "searchKeywords": keyword }] 
     } 
     }, 
     { 
     path: 'postSubTopics', 
     match: { '$or': [ 
      {'key': subtopic}, 
      { "searchKeywords": keyword }] 
     } 
     } 
    ]; 

keystone.list('Posts').model 
.find({'state': 'published', 
      'publishedDate': {'$lte': currentDate}}) 
.populate(populateObjects) 
.sort({'publishedDate': -1}).lean() 
.exec(function (err, result) { 
result = result.filter((doc) => {//logic to check if wanted fields are populated} 
} 



// In another file... 

    PostsPaginator.getPostsFromPostsArray = function(req, res, postsArray, pageNumber, postsPerPage) { 
     /*attributes: 
      pageNumber - number: the current page we are displaying for 
      totalPosts - number: total number of posts that exist for the query 
      totalPages - number: total number of pages there will be for pagination 
      pagePosts - array: the posts that will be returned to display for the page 
      isValidPage - boolean: if invalid page number is input return false 
      pagePath - string: the url path of the page requested 
      */ 
     var posts = {}; 
     postsPerPage = postsPerPage || 10; 
     posts.pageNumber = pageNumber; 

     posts.totalPosts = postsArray.length; 
     posts.totalPages = Math.ceil(postsArray.length/postsPerPage); 

     var start = postsPerPage * (pageNumber - 1); 
     var end = postsPerPage * pageNumber; 
     posts.pagePosts = postsArray.slice(start, end); 
     posts.isValidPage = start <= posts.totalPosts; 
     posts.pagePath = req.path; 
     return posts; 
    }; 
Смежные вопросы