我在Laravel应用程序中创建了一个API来提取所有客户端(3000+)的详细信息,以便我可以使用我的AngularJS自动填充表单来搜索他们的姓名/地址/电话号码等。
API输出大约1,000Kb的客户端数据(json)。如果我没有获取所有数据,我可以认为在搜索框中输入他的名字时客户端不存在,所以我希望能够加载它们。
一切正常,但1000Kb的下载速度很慢。虽然AngularJS处理得很好。如果我有10,000个客户怎么办?
我应该在哪里提高此抓取的性能:
以下是我使用的代码:
API控制器
public function index()
{
$clients = Client::where('business_id', '=', \Auth::user()->business_id)->orderBy('updated_at', 'DESC')->get();
return Response::json([
'clients' => $this->transformClientCollection($clients)
], 200);
}
public function transformClientCollection($clients)
{
return array_map([$this, 'transformClient'], $clients->toArray());
}
public function transformClient($clients)
{
return [
'clientid' => $clients['id'],
'first_name' => $clients['first_name'],
'last_name' => $clients['last_name'],
'address_1' => $clients['address_1'],
'address_2' => $clients['address_2'],
'city' => $clients['city'],
'state' => $clients['state'],
'postal_code' => $clients['postal_code'],
'phone_number_1' => $clients['phone_number_1'],
'phone_number_2' => $clients['phone_number_2'],
'email' => $clients['email']
];
}
AngularJS(html文件)
<div ng-app="instantsearch">
<div ng-controller="instantSearchCtrl">
<div class="row">
<div class="col-sm-12">
<input type="text" class="form-control search" ng-model="searchString" placeholder="Enter your search terms" />
</div>
</div>
<div class="row data-ctrl" ng-repeat="i in items | filter:searchString | limitTo:20 ">
<div class="col-sm-12">
@{{ i.first_name }} @{{ i.last_name }} @{{ i.address_1 }} @{{ i.address_2 }} @{{ i.city }} @{{ i.state }} @{{ i.phone_number_1 }} @{{ i.phone_number_2 }} @{{ i.email }}
</div>
</div>
</div>
</div>
AngularJS(JS档案)
var app = angular.module('instantsearch',[]);
app.controller('instantSearchCtrl',function($scope,$http,$location){
var urlapiclients = $location.protocol() + "://" + $location.host() + "/api/clients" ;
$http.get(urlapiclients).success(function(data, status, headers, config) {
$scope.items = data.clients;
}).error(function(data, status, headers, config) {
console.log("No data found..");
});
});
app.filter('searchFor', function(){
return function(arr, searchString){
if(!searchString){
return arr;
}
var result = [];
searchString = searchString.toLowerCase();
angular.forEach(arr, function(item){
if(item.first_name.toLowerCase().indexOf(searchString) !== -1){
result.push(item);
}
});
return result;
};
});
JSON输出
"clients":[
{
"clientid":4981,
"first_name":"Sid",
"last_name":"Hodkiewicz",
"address_1":"6659 Hackett Ways",
"address_2":"",
"city":"New Estherville",
"state":"Tennessee",
"postal_code":"27281-0870",
"phone_number_1":"00700300842",
"phone_number_2":"",
"email":"hNitzsche@Stokes.biz"
},
{
"clientid":4982,
"first_name":"Braulio",
"last_name":"Bechtelar",
"address_1":"7558 Anne Land Suite 876",
"address_2":"",
"city":"Rauview",
"state":"Alabama",
"postal_code":"01837-9601",
"phone_number_1":"1-017-001-8215",
"phone_number_2":"",
"email":"nBaumbach@gmail.com"
},
{
"clientid":4983,
"first_name":"Loma",
"last_name":"Dibbert",
"address_1":"805 Jones Fields Suite 411",
"address_2":"",
"city":"Lake Billychester",
"state":"New Jersey",
"postal_code":"69315-4595",
"phone_number_1":"(691)511-6275x891",
"phone_number_2":"",
"email":"dHegmann@Bashirian.net"
},
{
"clientid":4984,
"first_name":"Verla",
"last_name":"Schulist",
"address_1":"89529 Bode Village Suite 344",
"address_2":"",
"city":"West Jessy",
"state":"Virginia",
"postal_code":"69116",
"phone_number_1":"(248)211-3643",
"phone_number_2":"",
"email":"Friesen.Ruthie@Hand.biz"
},
{
"clientid":4985,
"first_name":"Jimmie",
"last_name":"Fadel",
"address_1":"4355 Marquardt Heights",
"address_2":"",
"city":"South Conrad",
"state":"District of Columbia",
"postal_code":"55751",
"phone_number_1":"(414)901-2495",
"phone_number_2":"",
"email":"Koepp.Wayne@yahoo.com"
}
答案 0 :(得分:0)
是的......要求1 MB下载自动完成功能可能不是一个好主意。您有两个主要选择:
选项1适用于较小的列表,您当然可以使用比当前使用的有效载荷小得多的API调用。
一旦您的应用程序扩展到一定的大小,选项2就成为唯一的解决方案。缺点是它不如将所有内容加载到内存中那么快。
答案 1 :(得分:0)
返回数据库中的每一行只是为了在Javascript中搜索它似乎有点过分。目前它可能只有3000个客户端,但我假设这个表是为了随着时间的推移而增长,并且随着时间的推移只会越来越慢。
实现此目的的最佳方法是仅返回与从Javascript应用程序传递的搜索查询匹配的客户端。例如,您可以发出请求:
http://www.example.com/api/v1/clients?search=foo
在服务器端,您可以执行以下操作:
$search = '%'.Input::get('search').'%';
// Just a few of the columns to search
$clients = Clients::where('first_name', 'LIKE', $search)
->orWhere('last_name', 'LIKE', $search)
->orWhere('state', 'LIKE', $search)
->take(10)
->get();
请记住,减少收集大小会减少从MySQL服务器传递到PHP(可能本身很慢)以及通过网络传递给Angular应用程序的数量。
回应你的评论:
I've added examples of my code and output above. I could lose a few Kb if I changed the names address_1 to a1 and phone_number_1 to p1 for example, but besides that....
这对问题是一个最小的绑定,我不一定建议重命名返回的密钥。