Hugoware

The product of a web developer with a little too much caffeine

Posts Tagged ‘jLinq

Waiter, There Is Some jQuery In My jLinq…

leave a comment »

jLinq occasionally gets confused as a plug-in for jQuery. Unfortunately, jLinq doesn’t do much to help performing queries in jLinq. I’ve written some extension methods before to help link the two together but they were packaged with other projects (and not really ever released)

So this weekend I put together a few helpful extension methods and released them on GitHub.

Naturally, you’ll need the core jLinq library and the jLinq.jQuery library along with jQuery. Since a lot of jQuery uses chained methods you’ll need to use the special invoke syntax for jLinq queries (just an array).

Here are some of the commands you can use.

  • jlinq.$([selector]) : Starts a new query from document.body with the starting selector (if any).
  • $(selector).query([selector]) : Starts a new query from the current jQuery object. Allows an optional selector.
  • .include(selector, [jQuery Object]) : Includes the matches of the provided selector into the current query. You can use a different jQuery object as the source (otherwise it defaults to the object that started the query).
  • .get([selector]) : Converts the current matches in the query to a jQuery object. Allows an optional selector to further filter the results.

Just as a reminder, in order to invoke methods within a query you need to use an array where the first value is the name of the method and following values are the arguments. These arguments are all where the field name would normally be. Here are a few examples in case you need them.


//Example 1: Non-method query
jlinq.from(data).contains(
    "fieldName", //the field to pull the value from
    "check for this" //the argument for contains
    );

// Example 2 : No arguments
// function test() { ... }
jlinq.from(data).contains(
    ["test"], //no arguments, but still an invoke
    "check for this" //the argument for contains
    );

// Example 3 : With arguments
// function test(arg1, arg2) { ... }
jlinq.from(data).contains(
    ["test", 33, false], //the method with arguments
    "check for this" //the argument for contains
    );

So what do these new methods look like? Well here are a few examples to get you started!


//finds all .result elements containing red or green
//and is also case-insensitive
jlinq.$("div.results")
    .contains(["text"], "red")
    .or("green")
    .get()
    .appendTo(document.body);

//finds all links pointing to MP3 files then sorts and styles them
var mp3Links = jlinq.$("a")
    .endsWith(["attr","href"], ".mp3")
    .sort(["text"])
    .get()
    .css({
        color:"#f00",
        fontWeight:"bold"
    });

//highlights all of the matching markup with 'Joe Smith'
$("div.result").query()
    .contains(["html"], "Joe Smith")
    .each(function(rec) { 
        var markup = rec.html()
            .replace(/Joe Smith/g, 
                "<span class='highlight'>Joe Smith</span>");
        rec.html(markup); 
        });

Now you can enjoy the awesomeness of jQuery along with the semi-usefulness of jLinq! You have access to ‘or’-ing, case insensitivity, sorting — It is all there!

This code is all brand new so I don’t recommend using it anywhere important just yet, but it is fun to see how jLinq can make queries a little bit easier.

Written by hugoware

September 26, 2010 at 10:18 pm

Using jLinq With JSON APIs

leave a comment »

I’ve had a few e-mails asking how to perform a query on JSON data from an external source, for example Flickr Services. This post we will go over accessing Flickr data but also performing a secondary query on the information returned.

You can download a .zip file at the end of the post with the files used in the examples.

Let’s take a look at what we’re going to create…

You can see we’ve included a search box along with a few additional check boxes with options we can use for the secondary query. These options aren’t available for the API call, but we can intercept the records and apply additional filters before we use them on the page.

To start, we need to create an extension method for downloading the data from the Flickr APIs. jLinq allows you to create extension methods and plug them directly into the framework.

//extend jLinq to search Flickr
jlinq.flickr = function(search, action) {
    search = escape(search);
    $.getJSON(
        "http"+"://api.flickr.com/services/feeds/photos_public.gne?"+
        "tagmode=any&format=json&jsoncallback=?&tags="+search, 
        function(data) {
            var query = jlinq.from(data.items);
            action(query);
        });
};

This example creates a method named flickr that resides with the rest of the jLinq library. The method accepts a keyword to search with and an anonymous function that will be used to work with the data. This is because we have to wait for the server to return a response.

This means you would use the function with a search phrase and a jLinq query to perform.

//start a new jLinq query
jlinq.flickr("cake", function(query) {

    //perform a normal query and use the data
    query.contains("title", "red")
        .sort("title");
});

At this point we need to wire up all of the UI elements on the page. I won’t go into detail on this part but you can always refer to the example for help if you get stuck.

So lets take a step back and take a look at how the filtering is done for the records. You’ll notice that we can selectively perform certain parts of the query depending on which check boxes are selected.

//sample.js - line 31     - - - - - -
//if excluding titles with digits
if (flickr.ui.filterNumbers.is(":checked")) {
    query.notMatch("title", /\d/g);
}

//if requiring a photo to have a title
if (flickr.ui.requireTitle.is(":checked")) { 
    query.notEmpty("title"); 
}

//if requiring sorting of titles
if (flickr.ui.sortTitle.is(":checked")) { 
    query.sort("title"); 
}

//snip...

You’ll notice that you don’t have to chain the entire query together. You can do sections at a time. This means you can decide when certain parts of the script run and when they are skipped.

Now, we can write queries against Flickr and also perform our own secondary queries using jLinq. In this case we are sorting data and filtering out records that wasn’t part of the query to the server.

Of course, this is a simple example but is does show some of the neat ways you can you can use jLinq to help you work with JSON data.

[Sample Files]
http://hugoware.com/examples/jlinq-flickr.zip

Written by hugoware

August 26, 2010 at 1:12 am

3 Things To Know Before Using jLinq

leave a comment »

Since I released the beta code for the new jLinq I’ve had several of the same questions show up. Here are some answers to help you get started.

Where Is ‘Manual’, Query Commands Are ‘Auto-pilot’

I’ve had a few questions where people start trying to use the where command and find that it isn’t solving anything.

As far as I can tell, a lot of other LINQ style Javascript libraries use Where as their query command and have the developer manually provide the comparisons. Granted, I don’t know the other frameworks very well (hint, I wrote my own) but a lot of the code samples look something like this.

var results = lib.From(data)
    .Where(function(record) { return record.name.substr(0, 1) == "a"; })
    .OrderBy(function(record) { return record.name; })
    .Select();

I’m sure that these libraries are doing a lot of stuff for you in the background, but the where command in itself seems like placing too much work on the developer.

jLinq approaches this differently. Instead, you’ll find many common query methods included as part of the library. These methods also evaluate the data types to determine the best way to query the property.

Here is an example, consider you have some data that looks like this.

var data = [{
    name: "James",
    permissions: ["read", "write", "delete"]
},
/* snip... */];

Instead of checking these records manually, you can use the same command for both properties and they will handle the data differently for each.

//with string types
jlinq.from(data).contains("name", "e").select(); //matches the 4th 'e' in 'James'

//with array types
jlinq.from(data).contains("permissions", "write").select(); //matches the 2nd 'write'

This reduces the typing you do since you no longer have to perform manual comparisons.

Of course, jLinq does include a where command that uses the same syntax as the example above (anonymous function), but it is recommended to create extension methods instead of using the where command.

Operators Are Query Commands Too

Operators are an important part of jLinq. Sometimes you’d like to match on more than one condition or ignore records that do not meet a certain condition. You can use operators as individual commands in your queries.

//Examples only - Shorter syntax explained in Section 3

jlinq.from(data)
    .starts("first", "a")
    .or()
    .starts("first", "b");

jlinq.from(data)
    .not()
    .starts("first", "d")

jLinq takes operators a step further by creating operator aliases for all of the query commands in your library. This means that instead of only having the query command starts you actually have 6 – starts, orStarts, andStarts, notStarts, orNotStarts, andNotStarts. The queries above can be rewritten as.

//Examples only - Shorter syntax explained in Section 3

jlinq.from(data)
    .starts("first", "a")
    .orStarts("first", "b")
    .select()

jlinq.from(data)
    .notStarts("first", "d");

It is worth noting that and is the implied default unless you provide an or – the and versions of the query commands are for aethestetics only. 🙂

DRY — I Repeat, DRY!

If you aren’t familiar with the term DRY, it means “Don’t Repeat Yourself”. The previous samples reduced some of our typing, but jLinq can actually take it a step further.

jLinq uses field and command memorizing, meaning after you say it once it is implied until you say something different.

jlinq.from(data)
    .starts("first", "a")
    .or("b")
    .or("c");

jlinq.from(data)
    .starts("first", "a")
    .ends("b")
    .or("last", "a");

The first example memorizes the command being used is starts and the field being queried is first. After that, the remaining calls to ‘or’ will repeat the previous command and field unless something else is used.

The second example shows how you can mix up commands and field names without needing to repeat yourself. Basically, here is what the query is doing.

  1. Records with first names starting with ‘a’…
  2. then records with first names ending with ‘b’…
  3. then records with last names ending with ‘a’

You can see that jLinq makes it easy to avoid repeating the same commands and field names to reduce the typing.

This is just some of the first basics to understand about jLinq. I’ll be blogging more (and writing documentation) for the next few days. Feel free to contact me with questions.

Written by hugoware

August 11, 2010 at 9:54 pm

jLinq Reloaded

with 5 comments

[jLinq Beta is now online – go check it out!]

My first ‘open source’ project I ever released was a Javascript library that allowed you perform LINQ style queries with arrays of objects. The library supported operators, extension methods and even memorized commands to reduce typing.

Overall, it did a good job of making it easier to select information that normally would need to be handled with a for loop. Unfortunately, it turns out jLinq is rather slow. I recently blogged about a performance evaluation that came back with less than flattering results.

However, this is exactly where ‘open source’ helps make better software. If I hadn’t released my code then I might never know how it could be improved. This is the sort of thing that inspires software developers to improve their code — and that is exactly what is did for me.

So for the past few days I’ve been completely rewriting jLinq from the ground up and the gains have been incredible to say the least.

  1. About 60% smaller (around 8kb compressed)
  2. 99% faster queries
  3. Easier to extend library
  4. Minty fresh scent (your results may vary)

If you’re looking for a download link then you’re going to have to contact me instead. The code should be released soon but for now I’m still writing tests and preparing to rerelease the project with a brand new site (and probably a new name).

[http://github.com/hugoware/jlinq-beta/]

There has been a lot of interest already in seeing the new code so I’ve started a new repository on github.com. This is beta code so I suspect I’ll have errors in it. Please feel free to contact me to log an issue on the site.

If you’re interested in how jLinq improved so much then read on…

jLinq… But On Caffeine

My first theory about why jLinq was so slow had to do with the use of evals in my code.

At the time, I didn’t understand you could pass functions as arguments, I certainly had no idea what enclosures were, so jLinq would build an entire query in a string and then eval it into a method that could be invoked against each record.

I also used eval to get values from records instead of just referring to them by their names as an index. I don’t know why eval is so much slower, but the difference is undeniable.

//using index names
var fast = function(obj, path) {
    path = (path+"").split(/\./g);
    var index = 0;
    while(obj != null && index < path.length) {
        obj = obj[path[index++]];
    }
    return obj;
};

//being lazy with an eval
var slow = function(obj, path) {
    return eval("obj."+path);
};

//looping 100,000 times
loop(100000, function() { fast(data, "name.first"); }); //128ms
loop(100000, function() { slow(data, "name.first"); }); //6.8 minutes

So what kind of improvement do these two changes result in? Big ones.

Single Argument Query (850 Records)
Previously: ~430ms
Now: ~10ms

Multi-Argument Query with Strings (850 Records)
Previously: ~2730ms
Now: ~35ms

Simple Join (850 Records)
Previously: ~6200ms
Now: ~135ms

The list of improvements goes on but I’ll talk about them more in later blog posts.

So What Is Next?

It’s screaming fast and much smaller but unfortunately it is too new to even suggest that it is put into production. I’ll definitely feel more confident in the code after I’ve finished the tests.

But I also plan to rebrand the library this time. Why?

As it turns out, the name LINQ has caused some confusion with non-.NET developers. I’ve heard that some developers see the name and say ‘Well, I don’t use .NET so I don’t need this.’, which is clearly not the response I’d like to hear.

jLinq isn’t only for web pages. In fact, the neat thing about jLinq is that it can be plugged into anything running Javascript and it works great. I’d like to see jLinq be exposed to more developers.

So, with a new name, new site and all brand new code I think there is a chance to redefine what jLinq can do for the community.

The code is mostly finished so now it’s time for the hard part… coming up with a good name…

Written by hugoware

August 8, 2010 at 8:53 pm

jLinq Performance Analyzed

with 2 comments

After writing this post I went back and rewrote jLinq from the ground up to improve performance.

So here is something interesting. Another developer named Dan Stocker has been working on a Javascript sorting library named jOrder and used jLinq for comparing benchmarks. The results are interesting to say the least.

Dan has a good write up of the results in the wiki for his project.

I’m disappointed, but in a good way. I thought jLinq was ‘good enough’. It performed the way it should and that was good enough for me. These results tell a much different story.

jLinq probably performs well in typical scenarios, whereas these benchmarks are for medium to large arrays queried thousands of times. I’ve used it in several projects with great results.

Regardless, jLinq clearly performs slower than it should. Reviewing the jLinq code I can think of a few potential pain points.

  1. The entire jLinq object and all of the commands are generated each time a query is started. jLinq there should be a way to cache a standard jLinq object and only rebuild it when needed.
  2. jLinq uses a lot of evals that probably could have been avoided if I understood Javascript better at the time. This undoubtedly is going to cause a significant performance hit.

jLinq was written just about a year and a half ago and I’ve since learned some of the finer parts of Javascript which would most likely improve the performance of the library. In fact, seeing this review has really inspired me to get into back into the project and see what kind of improvements I can make.

I appreciate Dan showing these results to me. Sharing your code with others is a great way to get feedback about what you write… even if it is a kick in the butt.

Written by hugoware

August 4, 2010 at 8:43 am

jsshell – Reputable Software??

with 2 comments

Yes, it seems impossible so I took a screenshot. My little jsshell project has made it onto a pretty ‘notable’ list of Google extensions.

If you don’t know what jsshell then you might watch the introduction screencast.

Well… yeah, it isn’t spelled correctly… but I promise it is the same one.

In any case, you can check out the list on the Google site for yourself and possibly pick up some of the other awesome plugins while you’re at it. Don’t wait too long since it is only a matter of time before they realize their mistake 🙂

So, what better way to celebrate than to go ahead and open-source the code?

As usual, you’ll find my code out on git-hub, since its, ya’know, awesome… GitHub that is…

[Source Code]
http://github.com/hugoware/jsshell

Written by hugoware

June 28, 2010 at 10:56 pm