Javascript 如何处理node.js数组中的超大数据
我正在一个Node.js服务器上工作,该服务器使用JSON进行响应。我有一个包含数据的旧服务器。js服务器充当连接用户和数据的中间人。传统服务器以csv形式返回数据,列为键,行为对象。我想把它转换成一个json对象数组。我正在使用此工具来完成以下任务:。我可以让工具为我构造输出,也可以用传入的每一行调用一个函数,然后自己构造它。我现在做的是后者 我的应用程序的用户可以传入搜索值,这意味着只应返回包含此值的行。用户还可以传入筛选器键和值,这意味着只应返回键包含每个键的值和给定值的行。当然,它们可以同时给出搜索值和筛选值,也可以两者都不给出。它们还提供一个排序键,该键是对数组进行排序所依据的对象中的键。它们也给我一个排序顺序:升序或降序。它们还为我返回一个页面大小和偏移量,用于分页 我的问题是,处理可能包含数百万行的数据集的最佳方法是什么?我无法修改旧服务器。这是我的。这是可行的,但我希望尽可能提高性能。有没有更有效的方法来进行排序、搜索、筛选、分页等?添加到数组然后进行排序是否比在添加过程中使用二进制搜索树和排序更好?有没有一种方法可以使用流来提高性能?我希望服务器受到CPU性能而不是RAM的限制。我正在寻找更好的性能的任何建议。谢谢!:) 编辑:还有,下面代码的哪一部分被阻塞了Javascript 如何处理node.js数组中的超大数据,javascript,node.js,performance,sorting,Javascript,Node.js,Performance,Sorting,我正在一个Node.js服务器上工作,该服务器使用JSON进行响应。我有一个包含数据的旧服务器。js服务器充当连接用户和数据的中间人。传统服务器以csv形式返回数据,列为键,行为对象。我想把它转换成一个json对象数组。我正在使用此工具来完成以下任务:。我可以让工具为我构造输出,也可以用传入的每一行调用一个函数,然后自己构造它。我现在做的是后者 我的应用程序的用户可以传入搜索值,这意味着只应返回包含此值的行。用户还可以传入筛选器键和值,这意味着只应返回键包含每个键的值和给定值的行。当然,它们可以
function searchRow(row, search) {
if (search) {
for (var key in row) {
if (row.hasOwnProperty(key) && row[key].toString().toLowerCase().indexOf(search.toLowerCase()) > -1) {
return true;
}
}
return false;
} else {
return true;
}
}
function filterByField(obj) {
return obj.field === this.valueOf();
}
function filterRow(row, filter) {
if (filter) {
filter = JSON.parse(decodeURIComponent(filter));
var passed = true;
for (var key in filter) {
if (filter.hasOwnProperty(key)) {
var index = row[key].toString().toLowerCase().indexOf(filter[key].toString().toLowerCase());
passed = passed && (index > -1);
}
if (!passed) {
break;
}
}
return passed;
} else {
return true;
}
}
function orderByKey(key, reverse, a, b) {
return function (a, b) {
var x = (a[key] || '').toString().toLowerCase();
var y = (b[key] || '').toString().toLowerCase();
if (x > y) {
return reverse ? -1 : 1;
} else if (y > x) {
return reverse ? 1 : -1;
} else if (hash(a) > hash(b)) {
return reverse ? -1 : 1;
} else if (hash(b) > hash(a)) {
return reverse ? 1 : -1;
} else {
return 0;
}
};
}
function sortedInsert(element, array, key, reverse) {
array.splice(locationOf(element, array, key, reverse) + 1, 0, element);
return array;
}
function locationOf(element, array, key, reverse, start, end) {
if (array.length === 0) {
return -1;
}
start = start || 0;
end = end || array.length;
var pivot = parseInt(start + (end - start) / 2, 10);
var c = orderByKey(key, reverse, element, array[pivot]);
if (end - start <= 1) {
return c == -1 ? pivot - 1 : pivot;
}
switch (c) {
case -1: return locationOf(element, array, key, reverse, start, pivot);
case 0: return pivot;
case 1: return locationOf(element, array, key, reverse, pivot, end);
}
}
function getTable(path, columns, delimiter, query) {
var deferred = q.defer();
var headers = [];
var data = [];
delimiter = delimiter ? delimiter : '\t';
var converter = new Converter({
delimiter: delimiter,
noheader: true,
headers: columns,
workerNum: os.cpus().length,
constructResult: false
});
converter.on("error", function(errMsg, errData) {
deferred.reject(errMsg);
});
converter.on("record_parsed", function(row) {
if (searchRow(row, query.search) && filterRow(row, query.filter)) {
sortedInsert(row, data, query.sort || headers[0].split("!").pop(), query.order === 'desc');
}
});
converter.on("end_parsed", function() {
var offset = parseInt(query.offset || 0);
var limit = parseInt(query.limit || data.length);
var total = data.length;
data = data.slice(offset, offset + limit);
deferred.resolve({
"total": total,
"rows": data
});
});
var options = {
url: config.url + path,
gzip: true,
method: 'GET'
};
request(options, function (error, response, body) {
if (error || response.statusCode != 200) {
deferred.reject(error);
}
}).pipe(converter);
return deferred.promise;
}
函数搜索行(行,搜索){
如果(搜索){
for(行中的var键){
if(row.hasOwnProperty(key)和&row[key].toString().toLowerCase().indexOf(search.toLowerCase())>-1){
返回true;
}
}
返回false;
}否则{
返回true;
}
}
功能过滤器Y字段(obj){
返回obj.field==this.valueOf();
}
函数filterRow(行,筛选器){
如果(过滤器){
filter=JSON.parse(decodeURIComponent(filter));
var通过=真;
for(过滤器中的var键){
if(filter.hasOwnProperty(键)){
var index=row[key].toString().toLowerCase().indexOf(过滤器[key].toString().toLowerCase());
通过=通过&(索引>-1);
}
如果(!通过){
打破
}
}
返回通过;
}否则{
返回true;
}
}
函数orderByKey(键、反向、a、b){
返回函数(a,b){
var x=(a[键]| |').toString().toLowerCase();
变量y=(b[键]| |').toString().toLowerCase();
如果(x>y){
反向返回?-1:1;
}如果(y>x),则为else{
反向返回?1:-1;
}else if(散列(a)>散列(b)){
反向返回?-1:1;
}else if(散列(b)>散列(a)){
反向返回?1:-1;
}否则{
返回0;
}
};
}
功能分类恐龙(元素、数组、键、反转){
数组.拼接(位置(元素,数组,键,反向)+1,0,元素);
返回数组;
}
函数位置(元素、数组、键、反转、开始、结束){
if(array.length==0){
返回-1;
}
开始=开始| | 0;
end=end | | array.length;
var pivot=parseInt(start+(end-start)/2,10);
var c=orderByKey(key,reverse,element,数组[pivot]);
if(end-start)您应该考虑使用数据库,比如MySQL(或者MongoDB,如果您更喜欢基于文档的)数据库是用来处理大量数据的,它比把它加载到内存中要有效得多。如果你不能改变遗留服务器,你可以做的是把数据从遗留服务器放到你自己的数据库中,然后再把它提供给用户。你也应该考虑缓存搜索结果来减轻负载。缓存只会是AB。le大约为60秒。将数据添加到数据库的开销值得吗?如果您的数组确实有数百万行,那么使用数据库肯定是值得的,而不是在搜索之前将整个数据加载到内存中。我同意Zhang的观点,但Alec必须找到保留“新数据库”的方法总是更新。