As part of my playing around with the GoogleReader API I needed to be able to search for items beyond a simple keyword search.

Since my last post I’ve extended my asynchronous C# wrapper (get latest code here) so the syntax has changed slightly  (took a lead from Simone to use lambdas – much better) and I’ve strongly typed all the responses, but you’ll get the idea.

Google expose a simple keyword search – under the hood you actually need to make two requests; a GET request to http://www.google.com/reader/api/0/search/items/ids?q=keyword… which will return the ids of the items found. Then you POST the ids to http://www.google.com/reader/api/0/stream/items/contents which returns the results.

This is all wrapped up for you by the following code which searches for anything to do with “Silverlight” in my Starred items.

GoogleReader.Search(“Silverlight”, ItemStateEnum.starred, (result) =>
    {
        // Do something with the items
        List<Item> items = result.Items;
 
    });

Or you can search over specific feeds with something like,

GoogleReader.Search("Silverlight", new FeedDescriptor(new Uri("http://feeds.timheuer.com/timheuer")), (result) =>
    {
        List<Item> items = result.Items;
    
        //...
    });

Or search over labels (tags and folder names),

GoogleReader.Search("Silverlight", new LabelDescriptor("Podcasts"), (results) =>
    {
        List<Item> items = results.Items;
    });

But what I actually wanted to be able to do was to search for any item that was a podcast, or more precisely contained some media – it may or may not have been tagged as such.

To do this and more complex searches is not currently possible via the Google Reader API so I created another overload for the search that takes a predicate.

So you can write something like,

GoogleReader.Search(
    (item) =>
    {
        // Write any method here that works with Item and returns a bool
        return (item.Enclosure != null || item.MediaGroup != null);
    },
    ItemStateEnum.reading_list,
    (result) =>
    {
        List<Item> items = result.Items;
    });

which will search over all my items for anything which contains some media.

This method will do a recursive search pulling back a set of items, searching through them and repeating until a set number of results have been found. This will obviously take more time to process so take care.

You can control how the search works by passing in additional filter options.

FilterOptions options = new FilterOptions();
options.MaximumNumberofResults = 10;
options.MaximumSearchableItems = 300;
options.SearchPageSize = 100;
 
GoogleReader.Search(
    (item) =>
    {
        // Write any method here that works with Item and returns a bool
        return (item.Enclosure != null || item.MediaGroup != null);
    },
    options,
    ItemStateEnum.reading_list,
    (result) =>
    {
        List<Item> items = result.Items;
    });

This will ensure that the search will complete once 10 results are returned or you search has gone through 300 items (100 at a time).

Full source code can be found here.