10/10/2018, 10:48

LINQ to Javascript <= Thư viện hot

Mình có phát triển một thư viện javascript, sử dụng để query object, array, list... Bà con nhảy vào chém hộ mình vài phát, trong quá trình phát triển, bà con chém nhẹ tay thôi

Tải phiên bản minify https://sourceforge.net/projects/lin...js.js/download
Tải js datasource trích từ database northwind https://sourceforge.net/projects/lin...nd.js/download, truy xuất bằng cách viết nortwind.Categories (bảng Categories), nortwind.Orders (bảng Orders)...


Một số hàm thông dụng
all(predicate) trả về nếu tất cả item thỏa điều kiện
any(predicate) trả về nếu một item bất kỳ thỏa điều kiện
select(action) nhận về tập hợp object được chọn lọc từ kết quả của hàm action
order(action, desc) nhận về một tập hợp đã được sắp xếp theo field trả về bởi hàm action
where(predicate) lọc tập hợp thỏa điều kiện predicate
array() chuyển tập hợp thành mảng để xử lý
dump() kết xuất nội dung tập hợp thành chuỗi
grid() kết xuất nội dung tập hợp thành html table
upper(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ hoa
lower(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
capitalize(action) kết xuất nội dung tập hợp, thông tin chọn lọc từ action, sau đó chuyển hóa thông tin thành chữ thường
...
Chỉ là một số hàm cơ bản, có tới vài chục hàm và những overload tham số hàm khác nhau, mình chưaa tiện document hết

Ghi chú: những tham số đa phần là action và predicate, 2 thứ này đều có thể là function hoặc string, action thường dùng chọn lọc nội dung kết xuất, predicate thường là biểu thức điều kiện return true / false

Những ví dụ cơ bản:
document.write(linq(northwind.Orders).grid()) // in ra danh sách tất cả hóa đơn
Code:
linq(northwind.Products).order(function() { return this.ProductName; }, true); // sắp xếp bảng sản phẩm theo thứ tự giảm dần của ProductName

linq(northwind.Products).order('ProductName', true) // tương tự như trên
linq([1, 2, 3, 4, 5, 6]).order(true) // sắp xếp giá trị giảm dần (không sử dụng field)
linq(northwind.Products).order('[ProductName, UnitsOnOrder]', [true, false])
linq(northwind.Products).order('[ProductName, UnitsOnOrder]') // sắp xếp theo nhiều field

linq(northwind.Products).where(function() { return this.CategoryID == 5 });
linq(northwind.Products).where('this.CategoryID'); //lọc theo điều kiện

linq(['hello', 'world']).capitalize() // trả về danh sách ("Hello", "World")
linq([1, 2, 3, 4]).odd() // trả về danh sách số lẻ (1, 3)
linq(["hello", "world"]).contains("d") // trả về danh sách những item có chứa chữ d
linq(["hello", "world"]).contains("D", true) // trả về danh sách những item có chứa chữ D và không phân biệt hoa thường
linq(["hello", "world"]).starts("h") // trả về danh sách những item có chữ h ở đầu

linq(northwind.Products).select(function() { return { name: this.ProductName, category: this.CategoryID }; });
linq(northwind.Products).select('ProductName')
linq(northwind.Products).select('[ProductName, CategoryID]') // kết xuất thành những item có kiểu dữ liệu mảng và có 2 phần tử chứa giá trị của ProductName, CategoryID
linq(northwind.Products).select('{ProductName, CategoryID}') // kết xuất thành những item có kiểu là object có thuộc tính ProductName và CategoryID chứa giá trị của những field ProductName và CategoryID 

linq([1, 2, 3, 4]).count() // đếm số item
linq([1, 2, 3, 4]).count('this % 2 == 0') // đếm số item là số chẵn

linq(3) tạo tập hợp số từ 0 đến 3 (0, 1, 2, 3)
linq(1, 5) tạo một tập hợp số từ 1 đến 5 (1, 2, 3, 4, 5)
linq("Hello world") tạo danh sách ký tự từ chuỗi ("H", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d")

linq([1, 2, 3, 4, 5]).each(function(key) { alert(this); }); // duyệt tập hợp

Khi lọc, select, order, group... hệ thống thực sự chưa query, chỉ đến khi kết xuất bằng những hàm array, get, each... thì nội dung query mới được thực thi. Tốc độ xử lý cũng không đến nỗi tệ, sort bảng Orders có ~800 mất 2-3 ms

Những hàm take, first, last, limit(chế thêm cho giống mysql limit), skip, group, join, min, max, sum, avg, concat, union, get(lấy item ở vị trí thứ i)
trinhdiep viết 12:52 ngày 10/10/2018
ha. doc title tuong la dung js de ket nối tới linq. có lẽ nên gọi là "linq trong js.(define linq in js)".
dùng dotnet thì nó có thư viện js khá lớn hỗ trợ cho dataobject và kết nối không đồng bộ với sevice. (datagrid,datagridview,datalist...)

mình cũng đề nghị thay cái
Code:
linq([1, 2, 3, 4, 5, 6]).order
sang dùng
Code:
[1, 2, 3, 4, 5, 6].order
và nếu muốn dùng
Code:
[1, 2, 3, 4, 5, 6].order('desc').first()
của bạn có lẽ phải viết là
Code:
linq(linq([1, 2, 3, 4, 5, 6]).order('desc')).first()
chưa xem code của bạn. xong ở đây không thấy có update và insert.
oh, quên mất không biết ý nghĩa của linq là gì. lâu lâu không nhòm là quên sạch

And thank
anhchanghaudau viết 13:04 ngày 10/10/2018
Được gửi bởi trinhdiep
ha. doc title tuong la dung js de ket nối tới linq. có lẽ nên gọi là "linq trong js.(define linq in js)".
dùng dotnet thì nó có thư viện js khá lớn hỗ trợ cho dataobject và kết nối không đồng bộ với sevice. (datagrid,datagridview,datalist...)

mình cũng đề nghị thay cái
Code:
linq([1, 2, 3, 4, 5, 6]).order
sang dùng
Code:
[1, 2, 3, 4, 5, 6].order
và nếu muốn dùng
Code:
[1, 2, 3, 4, 5, 6].order('desc').first()
của bạn có lẽ phải viết là
Code:
linq(linq([1, 2, 3, 4, 5, 6]).order('desc')).first()
chưa xem code của bạn. xong ở đây không thấy có update và insert.
oh, quên mất không biết ý nghĩa của linq là gì. lâu lâu không nhòm là quên sạch

And thank
Mình muốn đảm bảo những property nguyên mẫu của array, hạn chế thêm những hàm thừa vào array hay bất kỳ loại Object nào. vì như thế sẽ làm chậm tốc độ xử lý và sai lệch code
ví dụ nếu ko viết thêm prototype cho array thì khi
for(var i in myArray) nó chỉ duyệt qua những index của array

Khi có thêm prototype thì nó duyệt qua cả những method mới add vào thành ra phải thêm công đoạn kiểm tra đây có phải là method nội tại của array hay không rồi mới xử lý .v.v.

việc sử dụng linq(values).where().where().order().order().group ().group().first()
là hợp lệ, không phân biệt thứ tự trước sau của mệnh đề
Duy chỉ có những mệnh đề kết xuất first, last, array (những mệnh đề này không kết xuất thành kiểu liệt kê) nên sẽ không gọi nối tiếp những mệnh đề kia được.

Bạn nào muốn viết prototype cho array để dễ sử dụng thì có thể theo mẫu sau:

Object.prototype.linq = function() { return linq(this); };

Sử dụng: [1, 2, 3, 4].linq().odd();

Còn LINQ 2 javascript là cách gọi chung của những dạng xử lý của LINQ, ví dụ LINQ to Object, xử lý những đối tượng trong bộ nhớ chứ chả có kết nối CSDL chi cả, hoặc LINQ to XML, LINQ to File, LINQ to Web .v.v.

[=========> Bổ sung bài viết <=========]

Mình có so sánh một số thư viện LINQ cho javascript khác, sau đây mình chỉ nêu những tính năng nổi bật (các bác đừng cho là mình tự sướng), còn những tính năng không nổi bật thì mời bà con xông vào chém xối xả.

1. Cú pháp đơn giản và hỗ trợ string expression
linq([1, 2, 3]).where(function() { return true });
hoặc linq([1, 3, 4]).where('this % 2 == 0');

So với một số library khác chỉ sử dụng function() {} cho query
http://blog.foxxtrot.net/2010/06/lin...avascript.html
http://linqjs.codeplex.com/ phải thêm dấu $

2. Xử lý trên nhiều loại tập hợp, object list, value list, range, string, regex matches
linq('hello world') // chuỗi
linq(/\d+/, '12213123 213123 21312312') // regex matches
linq([1, 2, 3, 4]) // value list
linq([ {name: 'abc', age: 10}, {name: 'def', age: 11} ]) // object list
linq($('*')).where('this.tagName == "B"') // jquery
So với những thư viện khác chỉ xử lý độc nhất array hoặc object list không xử lý được value list vì những thư viện đó khi where phải cần field name:
http://www.hugoware.net/Projects/jLinq

3. Sắp xếp records trên nhiều fields, một số thư viện chỉ sắp xếp trên 1 field

4. Hỗ trợ tập lệnh query phong phú, sao chép gần đủ của .net, số lượng hàm query chỉ kém thư viện http://linqjs.codeplex.com/


5. Hỗ trợ xử lý trễ
var results = linq(northwind.Orders).where('this.OrderID != null'); // chưa xử lý lệnh where hoặc bất kỳ mệnh đề nào nối tiếp
var array = results.array(); // bắt đầu xử lý để kết xuất thành array

So với một số thư viện xử lý dựa trên cơ sở array thì ở mỗi mệnh đã được chuyển hóa thành array và xử lý ngay tại bước đó =>xử lý ngay khi khởi tạo dù không chắc query đã được sử dụng đến.


6. Hỗ trợ viết những extension cho query
LINQ.Enumerable.extensions.myselect = function(action)
{
return something;
};

linq([1, 2, 3, 4, 5]).myselect();


Một số ví dụ khác:
Code:
 linq([1, 2, 3, 4, 5]).where(function() { return this % 2 == 0 }); // get even numbers

linq([1, 2, 3, 4, 5]).where('this % 2 == 0'); // use expression string 

linq(northwind.Orders).select(function() {
  return { MyOrderID: this.OrderID };
}); // list of object 

linq(1, 5); // range from 1 to 5

linq(5) // range from 0 to 4

linq("String value"); // sequence of chars

linq(/\d+/, '123 456 789'); // regex matches

linq(1, 10).take(5);

linq(1, 10).skip(3).take(5); // linq(1, 10).limit(3, 5);

document.write(linq(northwind.Orders).grid());

document.write(linq(northwind.Orders).grid({ OrderID: "Order id text", CustomerID: "Customer ID text" })); // show only OrderID and CustomerID columns 

linq(northwind.Orders).select('OrderID'); // list of order id value

linq(northwind.Orders).select('[OrderID, CustomerID]'); // list of array

linq(northwind.Orders).select('{OrderID, CustomerID}'); // list of object

linq(['Hello', 'World']).starts('H') ;

linq(['Hello', 'World']).starts('h', true);

linq(['Hello', 'World']).contains('ll');

linq(['Hello', 'World']).like(/^H.+/);

linq(['Hello', 'World']).like('^h.+', 'i'); // use regex pattern string with options

linq(['Hello', 'World']).each(function() { alert(this) });

linq(['Hello', 'World']).invoke('charAt', 0); // get first char

linq(['Hello', 'World']).order(); // ascending

linq(['Hello', 'World']).order(true); // descending

linq(['Hello', 'World']).order(function() { return Math.random(); }); // randomize

linq(['Hello', 'World']).order(function() { return Math.random(); }, true); // randomize

linq(['Hello', 'World']).order('Math.random()'); // randomize

linq(northwind.Orders).order('[OrderID, CustomerID]'); // multiple fields

linq(northwind.Orders).order('[OrderID, CustomerID]', [false, true]); //  OrderID ASC, CustomerID DESC 

linq([1, 2, 3, 3, 4]).distinct();

linq([1, 2, 3, 3, 4]).first();

linq([1, 2, 3, 3, 4]).last();

linq([1, 2, 3, 3, 4]).count();

linq(['Hello', 'World']).upper();

linq(['Hello', 'World']).lower();

linq(['Hello', 'World']).capitalize();
anhchanghaudau viết 13:02 ngày 10/10/2018
chả bác nào nhảy vào chém cả, bùn nhỉ
bka viết 13:04 ngày 10/10/2018
cảm giác là không đc dynamic cho lắm
anhchanghaudau viết 12:50 ngày 10/10/2018
Được gửi bởi bka
cảm giác là không đc dynamic cho lắm
Mình chưia hiểu ý bạn lắm, dynamic là như thế nào, cơ bản vì javascript có hạn chế, nên tập linq này support cho những công việc compare, tìm kiếm giá trị một cách nhanh chóng
trinhdiep viết 12:49 ngày 10/10/2018
Được gửi bởi anhchanghaudau
Còn LINQ 2 javascript là cách gọi chung của những dạng xử lý của LINQ, ví dụ LINQ to Object, xử lý những đối tượng trong bộ nhớ chứ chả có kết nối CSDL chi cả, hoặc LINQ to XML, LINQ to File, LINQ to Web .v.v.
Nhưng bạn đã nghe ai gọi Linq to c#, Linq to java, linq to php chưa. mới thấy gọi là "linq for javascript".

nói chung bạn giữ quan điểm của bạn thì tùy. xong cũng nên nghĩ người sử dụng sẽ như thế nào.
lấy ví dụ jquery. chẳng ai viết là jquery("elementId").value="123"; chỉ cần thêm thư viện của jquery zô project là bạn có thể tận hưởng
theo tôi chì cách viết của bạn không chuyên nghiệp "bạn kia nói là không dynamic có lẽ cũng là ý này".
bạn có hỏi người dùng sẽ thích viết
linq([1, 2, 3, 4, 5, 6]).order hơn hay viết [1, 2, 3, 4, 5, 6].order hơn


một tiện ích mà mình nghĩ rất hay của linq là sử dụng kí pháp lambda
.select('u=>u.Title')
sẽ hay hơn là .select('this.Title'); sẽ rất hay nhầm lẫn với từ khóa this.
ví dụ
linq([1, 3, 4]).where('this % 2 == 0');
linq($('*')).where('this.tagName == "B"') // jquery
cùng là this nhưng ở 2 câu là khác nhau.
uoon viết 12:53 ngày 10/10/2018
Cố lên bạn ơi, hay bạn thử viết code rõ ràng lại + thêm chú giải nữa cho dễ theo dõi, nếu bạn muốn nhiều người góp ý thử làm một site riêng cho nó, rồi gửi email cho đồng chí này: ajaxians@ajaxian.com xem sao, chứ ở mình thấy ít người quan tâm tới cái js này lắm.
anhchanghaudau viết 12:55 ngày 10/10/2018
Được gửi bởi uoon
Cố lên bạn ơi, hay bạn thử viết code rõ ràng lại + thêm chú giải nữa cho dễ theo dõi, nếu bạn muốn nhiều người góp ý thử làm một site riêng cho nó, rồi gửi email cho đồng chí này: ajaxians@ajaxian.com xem sao, chứ ở mình thấy ít người quan tâm tới cái js này lắm.
Cảm ơn đóng góp của bạn.
Những cách nói linq2javascript đã có rất nhiều trên mạng, bạn có thể tham khảo, ở đây mình chỉ gọi cho dễ hiểu thôi.
Như mình đã trình bày, không phải mình không muốn viết cho nó ngắn gọn.
Nếu lý giải như bạn thì $('a').attr('href') thì tốt hơn hết jquery nên viết là 'a'.attr('href') cho nó tiện
còn việc bạn develop lại, sử dụng prototype hay ký hiệu $ cho nó ngắn gọn thì đó là quyền mỗi người, để làm chuyện này ko quá khó:
$ = linq;
$([1, 2, 3, 4, 5, 6]).order(); // trông như jQuery nhỉ
hay

Array.prototype.order = function() { return linq(this).order(); }
[1, 2, 3, 4, 5].order();

[=========> Bổ sung bài viết <=========]

Cập nhật bản mới https://sourceforge.net/projects/lin...28.js/download

Có thêm tính năng cài đặt vào các prototype có sẵn để dễ dàng sử dụng, mình cố gắng không cài đặt sẵn vào những prototyp do lo ngại bị xung đột khi sử dụng chung với những hàm tiện ích Moo hay Prototype framework. Do đó nếu bà con nào cảm thấy bất tiện trong code kiếc thì có thể dùng
LINQ.install(<overwrite>, <prototype hoặc class hoặc func>);
<overwrite> chỉ định rằng nếu là true sẽ ghi đè những hàm tiện ích của linq lên những hàm có sẵn của prototype đó nếu bị trùng tên, ngược lại false sẽ chỉ cài đặt những hàm của linq nếu prototype đó chưa có (nên dùng false để tránh xung đột)

Ví dụ:
Code:
LINQ.install(false, Array, String, Number);
hoặc LINQ.install(false, Array.prototype, String.prototype, Number.prototype); đều được cả

Sau đó có thể sử dụng

alert([1, 2, 3, 4, 5].event().dump());

var mynum = 100;

alert(mynum.event().dump()); // tìm những số chẵn từ 0 đến 99

alert("hello world".select(function(i) { return i % 2 == 0 ? this.toUpperCase() : this; } ).dump()); // biến đổi những ký tự ở vị trí chẵn thành chữ hoa

// có thể sử dụng LINQ.isntall('myprefix_', Array) để cài đặt hàm linq với tên có tiền tố chỉ định phía trước, khi đó ta sử dụng

[1, 2, 3, 4, 5].myprefix_where('this % 2 == 0');

hay LINQ.isntall('$', Array) và dùng [1, 2, 3, 4, 5].$where('this % 2 == 0');
anhchanghaudau viết 12:50 ngày 10/10/2018
Lên nào, bà kon ghé thăm blog của em để cùng thảo luận về vấn đề linq & javascript. Mình sẽ cố gắng sưu tầm cũng như chia sẻ những kinh nghiệm về javascript, vào đây nhá http://linq2js.blogspot.com/
Bài liên quan
0