2016-12-15 6 views
0

KeystoneJSでは、現在集計を使用してMongoを照会し、全体のセットを取得して戻しています。さて、私たちはより多くのデータを取得しており、改ページする必要があります。 KeystoneJSはページネーションをサポートしていますが、見た目からはwhereオプションパラメータでfindコマンドだけをサポートしています。 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'); 

私が通じページ付けできるようにしたいと思い、このから戻って返す結果は。私はそれをやるためにmongooseを使ったり、javascriptで配列をフィルタリングしたりしていますが、Keystoneにはページネーションが組み込まれていることがわかっているので、これがサポートされているかどうかを質問したいと思います。

答えて

0

はまず、あなたは、単に試してみました:私はマングースはボンネットの下にどのように動作するかに精通していないんだけれども

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

を私は本当に、それが動作してはならない理由として理由が表示されません。キーストーンは確かにあなたはそれのようなページネーションの呼び出しを行うことができます。

これを失敗すると、これを2つの呼び出しに分割できます。最初に、そのページ上の投稿のIDを取得し、それを配列に保存するために、投稿に対して標準のページネーションコールを行います。次に、作成した配列のIDを持つ投稿に最初に一致する集約コールを実行できます。値が配列hereにある場合の一致方法については、StackOverflowの記事があります。それはあなたが望むものを達成するはずですか?

最後に、すべての集計などが必要ですか?私は実際に集計を使用したことがないのでここで達成されているものは100%ではありませんが、代わりにポピュレートを呼び出すことができるポストの関係フィールドとしてpostTopicsを使用できますか?同様に、各トピックはそのサブトピックなどとの関係を持つことができます。私は、あなたのユースケースがこのために複雑すぎると思っていますが、私はそれをちょうど言いたいと思っていました。

+0

ありがとうございます。上記のクエリを試しただけでなく、多くのバリアントを試しましたが、どちらもうまくいきませんでした。上記の例では、集合体は関数ではないと不平を言っています。私はすべてのデータを取得してJSで自分自身のページングを行っています。 Mongoの集約フレームワークは人気が高まっているようですが、検索クエリの代わりに集約をサポートするためのキーストーンページネーション用の単純なプラグアンドプレイがあれば興味がありました。 – lshaffer

0

これを後で見つけた人にとって、私はMongooseを利用してこのクエリをクリーンアップすることができました。残念ながら、改ページでは、ポピュレート後のフィルタリングはまだ考慮されていないようです。ページ区切りは、where句に一致するすべての投稿を返しますが、人口の多いフィールドをさらにフィルタリングする必要がある場合は役に立ちません。私たちが人口を掘るまでに、ページネーションはすでに行われています。だから、最初に30ページ中10ページが返ってきたら、私はexecのフィルタを実行した後、10ページ中3ページしか終わらないかもしれません。私はKeystoneのページネートを使うのではなく、これを手助けするグローバルなPostsPaginatorオブジェクトを作成しました。

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; 
    }; 
関連する問題