EPiServer  /  Find November 23, 2011

Truffler update – dotting the i’s and crossing the t’s

NOTE Since writing this post the company behind Truffler, 200OK, has been sold to EPiServer and the product Truffler has been replaced by EPiServer Find. Most of the content of this blog post is however applicable to EPiServer Find as well. For questions regarding Find, be sure to visit the forum on EPiServer World.

Re-indexing of related pages, indexing and searching for VPP-files, geo sorting and several other awesome new features in Truffler's .NET API!

We’ve been pretty quiet regarding Truffler for a couple of weeks. That doesn’t mean that there hasn’t been any progress though. Quite the opposite. We’ve been getting a lot of interesting feedback, especially from users of our EPiServer module which we’ve been trying to respond to as quickly as possible. So, while there haven’t been any major new features (except for file search in the EPiServer module which is pretty major) there’s been plenty of minor additions and fixes. Not to mention documentation.

Sorting by geographical distance

When we’ve demoed the geo search features of Truffler (you have seen the map search, right?) we’ve often gotten questions regarding sorting by geographical distance. Apparently that’s something that many would find useful and also something that some other search engines can’t do. Here you have it Ler

var sergelsTorg = new GeoLocation(59.33234, 18.06291);

var result = client.Search<Restaurant>()
    .OrderBy(x => x.Location).DistanceFrom(sergelsTorg)
    .GetResult();

Delete by query/filter

In addition to deleting documents/objects from the index by ID it’s now also possible to delete all documents that match a filter. Just as with the Filter and BoostMatching methods we can use however complex filter expressions we want, but a simple example could look like this:

client.Delete<BlogPost>(x => x.Tags.Match("Banana"));

Don’t do exactly that though, bananas are good!

Cropping text in search results

From dog fooding ourselves as well as listening to feedback it’s become clear that it would be useful to fetch only parts of the text in a specific field when retrieving search results. We of course already have functionality for retrieving highlights, but at times we may want a part of the text even if there’s no matching keywords in a specific field. Therefor we’ve added an extension method for strings that is treated special in projection expressions named AsCropped. Using this method we can specify a maximum length to retrieve from a text field. The actual cropping happens on the search engine so this is also a good way to limit the amount of data sent over the wire.

var result = client.Search<Article>()
    .Select(x => new SearchResult { 
        Title = x.Title.AsCropped(50), 
        Text = x.Content.AsCropped(200)})
    .GetResult();

Indexing VPP files

In addition to PageData objects our EPiServer CMS integration now also automatically indexes page files. Technically there’s nothing stopping it from indexing all files in VPP folders, but considering that editors may not want all uploaded files publicly available in search results we’ve only enabled automatic indexing of page files by default. Of course, just like most other things in the Truffler .NET API this behavior can easily be changed with a few lines of code.

Note that given that files are Word or PDF documents etc it’s the actual content of the documents that are indexed. This is done by sending the actual documents to the search engine where they are analyzed. To protect from misusage or attacks we have a request size limit so if you need to index huge documents (over 5 megabytes) let us know and we’ll see if we can’t work something out Blinkar.

While it’s possible to search for all types of objects using the standard methods in the .NET API we’ve also added a convenience method for searching for files that take care of retrieving the actual indexed objects using the EPiServer API, similar to the method we’ve always had for PageData objects, GetPageResult. For VPP files this is called GetFilesResult and a simple usage example looks like this:

var result = client.Search<UnifiedFile>()
  .For("banana")
  .GetFilesResult();

EPiServer page dependencies

At times, especially when utilizing the document database-like features of ElasticSearch and Truffler, we want to denormalize data as much as possible. That is we want to index not only a single object but also the values in it’s nested objects (properties etc). A problem that arises then is however re-indexing these objects when one of the nested objects changes. To make it easier to handle such cases we’ve added a feature to automatically re-index related pages when a specific page is indexed.

For instance, let’s say that we’ve indexed the number of children that a page has. We’d then want to re-index parent pages when new child pages are indexed. This can be achieved by tweaking the PageIndexer class’ conventions:

PageIndexer.Instance.Conventions
  .ForInstancesOf<PageData>()
  .RelatedPages(x =>
  {
    var relatedPages = new PageDataCollection();
    if (!(x.PageLink.CompareToIgnoreWorkID(
                     PageReference.StartPage) 
         || x.PageLink.CompareToIgnoreWorkID(
                       PageReference.RootPage)))
    {
      relatedPages.Add(
        DataFactory.Instance.GetPage(x.ParentLink));
    }
    return relatedPages;
  });

Complex filtering

We’ve demoed and written quite a lot about the filtering DSL using the Filter method over the last couple of months. While the Filter method is great for defining criteria at compile time once people actually started using the API for building real applications it became clear that we needed better support for creating filters dynamically at runtime. Therefor we’ve added an extension method for the IClient interface that allows to create filters without actually defining a search request. Using this it’s much easier to handle scenarios where different filters should be applied depending on user input, such as when building the typical “advanced search” page. An example of using this, along with code, is shown at the sample site.

Documentation

Apart from new functionalities we’ve of course also added a bunch of new documentation, especially for the EPiServer integration and the new features. Check it out Ler

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer Find