2017-08-05 98 views
0

方案API分页,过滤,排序VS客户端分页,过滤,排序

  • 一个网站的页面将与分页,筛选,排序表视图。

  • 表中的数据是从REST API服务器获取的,数据包含 百万条记录。

  • 数据库< ---> REST API服务器< --->网络Sever的< --->浏览器


问题

  • 哪里会是分页,过滤,排序的最佳地点。

可能的解决方案

  • 分页,筛选,排序在Web服务器

    • REST API服务器发送完整的清单(所请求的实体可能不需要)
    • 网站服务器,进行分页,筛选,排序与逻辑可能增加负载
    • 如果Web服务器只是想只记录REST API服务器需要有单独的API为其他Web服务器已经从完整列表解析
  • 分页,筛选,排序在REST API服务器

    • REST API服务器需要输入参数和做分页,过滤,排序
    • Web服务器可以直接将其绑定到表视图没有格式化结果
    • 只请求的数据发送,从而节省带宽,
    • 更像是谷歌的融合表API

会是怎样做到这一点不违反REST API标准的最好方法?

回答

0

/*处理分页。 */ router.post( '/产品/视图前',函数(REQ,RES){

/* Set our internal DB variable */ 
var db = req.db; 

    /* Set our collection */ 
    products = db.get('products'); 

    pag_content = ''; 
    pag_navigation = ''; 

    page = parseInt(req.body.data.page); /* Page we are currently at */ 
    name = req.body.data.name; /* Name of the column name we want to sort */ 
    sort = req.body.data.sort == 'ASC' ? 1 : -1; /* Order of our sort (DESC or ASC) */ 
    max = parseInt(req.body.data.max); /* Number of items to display per page */ 
    search = req.body.data.search; /* Keyword provided on our search box */ 

    cur_page = page; 
    page -= 1; 
    per_page = max ? max : 20; 
    previous_btn = true; 
    next_btn = true; 
    first_btn = true; 
    last_btn = true; 
    start = page * per_page; 

    where_search = {}; 

/* Check if there is a string inputted on the search box */ 
if(search != ''){ 
    /* If a string is inputted, include an additional query logic to our main query to filter the results */ 
    var filter = new RegExp(search, 'i'); 
    where_search = { 
     '$or' : [ 
      {'name' : filter}, 
      {'price' : filter}, 
     ] 
    } 
} 

var all_items = ''; 
var count = ''; 
var sort_query = {}; 

/* We use async task to make sure we only return data when all queries completed successfully */ 
async.parallel([ 
    function(callback) { 
     /* Use name and sort variables as field names */ 
     sort_query[name] = sort; 

     /* Retrieve all the posts */ 
     products.find(where_search, { 
      limit: per_page, 
      skip: start, 
      sort: sort_query 

     }, function(err, docs){ 
      if (err) throw err; 
      // console.log(docs); 
      all_items = docs; 
      callback(); 

     }); 
    }, 
    function(callback) { 
     products.count(where_search, function(err, doc_count){ 
      if (err) throw err; 
      // console.log(count); 
      count = doc_count; 
      callback(); 
     }); 
    } 
], function(err) { //This is the final callback 
    /* Check if our query returns anything. */ 
    if(count){ 
     for (var key in all_items) { 
      pag_content += '<div class="col-sm-3">' + 
       '<div class="panel panel-default">' + 
        '<div class="panel-heading">' + 
         all_items[key].name + 
        '</div>' + 
        '<div class="panel-body p-0 p-b">' + 
         '<a href="products-single.php?item=' + all_items[key]._id + '"><img src="img/uploads/' + all_items[key].featured_image + '" width="100%" class="img-responsive" /></a>' + 
         '<div class="list-group m-0">' + 
          '<div class="list-group-item b-0 b-t">' + 
           '<i class="fa fa-calendar-o fa-2x pull-left ml-r"></i>' + 
           '<p class="list-group-item-text">Price</p>' + 
           '<h4 class="list-group-item-heading">$' + parseFloat(all_items[key].price).toFixed(2) + '</h4>' + 
          '</div>' + 
          '<div class="list-group-item b-0 b-t">' + 
           '<i class="fa fa-calendar fa-2x pull-left ml-r"></i>' + 
           '<p class="list-group-item-text">Quantity</p>' + 
           '<h4 class="list-group-item-heading">' + all_items[key].quantity + '</h4>' + 
          '</div>' + 
         '</div>' + 
        '</div>' + 
        '<div class="panel-footer">' + 
         '</p><a href="products-single.php?item=' + all_items[key]._id + '" class="btn btn-success btn-block">View Item</a></p>' + 
        '</div>' + 
       '</div>' + 
      '</div>'; 
     } 
    } 

    pag_content = pag_content + "<br class = 'clear' />"; 

    no_of_paginations = Math.ceil(count/per_page); 

    if (cur_page >= 7) { 
     start_loop = cur_page - 3; 
     if (no_of_paginations > cur_page + 3) 
      end_loop = cur_page + 3; 
     else if (cur_page <= no_of_paginations && cur_page > no_of_paginations - 6) { 
      start_loop = no_of_paginations - 6; 
      end_loop = no_of_paginations; 
     } else { 
      end_loop = no_of_paginations; 
     } 
    } else { 
     start_loop = 1; 
     if (no_of_paginations > 7) 
      end_loop = 7; 
     else 
      end_loop = no_of_paginations; 
    } 

    pag_navigation += "<ul>"; 

    if (first_btn && cur_page > 1) { 
     pag_navigation += "<li p='1' class='active'>First</li>"; 
    } else if (first_btn) { 
     pag_navigation += "<li p='1' class='inactive'>First</li>"; 
    } 

    if (previous_btn && cur_page > 1) { 
     pre = cur_page - 1; 
     pag_navigation += "<li p='" + pre + "' class='active'>Previous</li>"; 
    } else if (previous_btn) { 
     pag_navigation += "<li class='inactive'>Previous</li>"; 
    } 
    for (i = start_loop; i <= end_loop; i++) { 

     if (cur_page == i) 
      pag_navigation += "<li p='" + i + "' class = 'selected' >" + i + "</li>"; 
     else 
      pag_navigation += "<li p='" + i + "' class='active'>" + i + "</li>"; 
    } 

    if (next_btn && cur_page < no_of_paginations) { 
     nex = cur_page + 1; 
     pag_navigation += "<li p='" + nex + "' class='active'>Next</li>"; 
    } else if (next_btn) { 
     pag_navigation += "<li class='inactive'>Next</li>"; 
    } 

    if (last_btn && cur_page < no_of_paginations) { 
     pag_navigation += "<li p='" + no_of_paginations + "' class='active'>Last</li>"; 
    } else if (last_btn) { 
     pag_navigation += "<li p='" + no_of_paginations + "' class='inactive'>Last</li>"; 
    } 

    pag_navigation = pag_navigation + "</ul>"; 

    var response = { 
     'content': pag_content, 
     'navigation' : pag_navigation 
    }; 

    res.send(response); 

}); 

});

模块。exports = router;