Chris Umbel

Solrnet, a Solr Client Library for .Net

One of the strength's of Solr is it's ease of consumption by other platforms due to its REST API and response writers which include XML, JSON, native Ruby and native Python code.

If you're trying to consume a Solr service from .Net you could easily use a WebClient and parse the results with .Net's System.Xml namespace and perhaps even build an object wrapper on top of it. Luckily that work's already been done with the solrnet library.

In this post I'll outline the fundamentals of solrnet usage.

Prerequisites

This article assumes you have a .Net development environment such as Visual Studio and a functional Solr install in servlet container. I'll also assume that you understand how to configure Solr's schema. If that's not the case please consult the official Solr wiki.

Sample Schema

For demonstrative purposes I'll assume the following field declarations in schema.xml.

<fields>
  <field name="id" type="int" indexed="true" stored="true" required="true"/> 
  <field name="title" type="text" indexed="true" stored="true" required="true"/>
  <field name="content" type="text" indexed="true" stored="true" required="true"/>
  <field name="tag" type="string" indexed="true" stored="true" multiValued="true"/>  
  <field name="text" type="text" indexed="true" stored="false" multiValued="true"/>
</fields>

<copyField source="title" dest="text"/>
<copyField source="content" dest="text"/>
 
<defaultSearchField>text</defaultSearchField>
<uniqueKey>id</uniqueKey>

Project Setup

With the basic system in place now it's time to download solrnet from its project site on Google Code then add references to SolrNet.dll and Microsoft.Practices.ServiceLocation.dll (included with SolrNet) to a project.

Model

Now let's write some bloody code! Consider the following class declaration which defines the document's we'll be working with. In this case it's an article, much like a blog post, with a key, title, textual content and a list of tags.

Notice the SolrUniqueKey and SolrField attributes decorating the properties. That facilitates the mapping of the properties to field's in Solr.

using System;
using System.Collections.Generic;
using SolrNet;
using SolrNet.Attributes;
using SolrNet.Commands.Parameters;
using Microsoft.Practices.ServiceLocation;
  
class Article {
    [SolrUniqueKey("id")]
    public int ID { get; set; }

    [SolrField("title")]
    public string Title { get; set; }

    [SolrField("content")]
    public string Content { get; set; }

    [SolrField("tag")]
    public List<String> Tags { get; set; }
}

Writing Data

Model defined we can now connect to Solr and save some articles. The following code locates our Solr instance (running locally on port 8080 in my case), creates some documents and commits them to the index.

  
// find the service  
Startup.Init<Article>("http://localhost:8080/solr");
ISolrOperations<Article> solr =
     ServiceLocator.Current.GetInstance<ISolrOperations<Article>>();

// make some articles
solr.Add(new Article()
{
    ID = 1,
    Title = "my laptop",
    Content = "my laptop is a portable power station",
    Tags = new List<string>() { 
        "laptop", 
        "computer",
        "device"
    }
});

solr.Add(new Article()
{
    ID = 2,
    Title = "my iphone",
    Content = "my iphone consumes power",
    Tags = new List<string>() { 
        "phone", 
        "apple",
        "device"
    }
});

solr.Add(new Article()
{
    ID = 3,
    Title = "your blackberry",
    Content = "your blackberry has an alt key",
    Tags = new List<string>() { 
        "phone", 
        "rim",
        "device"
    }
});            

// commit to the index
solr.Commit();

Basic Querying

Of course the primary purpose of Solr is performing search queries. Consider the following examples which does a general full-text search on the word "power" and a tag search for "phone":

  
// fulltext "power" search  
Console.WriteLine("POWER ARTICLES:");
ISolrQueryResults<Article> powerArticles = solr.Query(new SolrQuery("power"));

foreach (Article article in powerArticles) {
    Console.WriteLine(string.Format("{0}: {1}", article.ID, article.Title));
}

Console.WriteLine();

// tag search for "phone" 
Console.WriteLine("PHONE TAGGED ARTICLES:");
ISolrQueryResults<Article> phoneTaggedArticles = solr.Query(new SolrQuery("tag:phone"));

foreach (Article article in phoneTaggedArticles)
{
    Console.WriteLine(string.Format("{0}: {1}", article.ID, article.Title));
}
which produces the following output
POWER ARTICLES:
1: my laptop
2: my iphone

PHONE TAGGED ARTICLES:
2: my iphone
3: your blackberry

Faceting

One of my personal favorite features of Solr is faceting which enables aggregate counts to be returned along with query results. Faceting is well supported in solrnet.

The following example displays counts per tag of articles matching the "device" tag:

Console.WriteLine("DEVICE TAGGED ARTICLES:");
ISolrQueryResults<Article> articles = solr.Query(new SolrQuery("tag:device"),
  new QueryOptions() {
    Facet = new FacetParameters
    {
        // ask solr for facets
        Queries = new[] { new SolrFacetFieldQuery("tag") }
    }
});

foreach (Article article in articles)
{
    Console.WriteLine(string.Format("{0}: {1}", article.ID, article.Title));
}

Console.WriteLine("\nTAG COUNTS:");

foreach (var facet in articles.FacetFields["tag"])
{
    Console.WriteLine("{0}: {1}", facet.Key, facet.Value);
}

with the following output:

DEVICE TAGGED ARTICLES:
1: my laptop
2: my iphone
3: your blackberry

TAG COUNTS:
device: 3
phone: 2
apple: 1
computer: 1
laptop: 1
rim: 1

Wrapping up

Solrnet makes consumption of a Solr service easy, but I've only covered the basic concepts here. Other features of Solr such as spell checking and match highlighting are also handled. The solrnet wiki will tell you more.

Mon Mar 08 2010 23:03:00 GMT+0000 (UTC)

9 Comments Comment Feed - Permalink
Solrnet does play a key role in enhancing the user friendly context of Solr. Solr's strength actually lies in the ease of consumption it renders to other platforms.Ur article was indeed very helpful. I read a similar kind of article giving an insight to upgraded version of solr at http://www.lucidimagination.com/Downloads/LucidWorks-for-Solr/Reference-Guide
by Phillips on Sat Mar 27 2010 07:03:38 GMT+0000 (UTC)
Hi,

Could you please give the sourcecode link for this article as I am not able to implement it.

Thanks
by Alok on Tue Aug 31 2010 09:42:37 GMT+0000 (UTC)
sure thing:

http://blobs.chrisumbel.com/SolrNetSample.zip
by chrisumbel on Tue Aug 31 2010 23:33:05 GMT+0000 (UTC)
Hi,
Thanks for posting this
Love the sample app as well.

I just have a few questions, which I've put on StackOverflow (with the intention of helping everyone)

http://stackoverflow.com/questions/3672605/where-how-to-fit-solr-into-asp-net-mvc-app-using-nhibernate-repository-patte

I'd really appreciate your input, as I'm sure this is something you have come across!
by Alex James Brown on Wed Sep 08 2010 23:14:31 GMT+0000 (UTC)
Hi,

I have an error and I really don't know what else to check.
The error is at this line:
 ISolrQueryResults<Article> powerArticles = solr.Query(new SolrQuery("power"));

Error: The remote server returned an error: (500) Internal Server Error.

The articles was added with success.

Can be a problem with some setting of Solr or Tomcat?

Thank you in advanced.
Radu
by radu on Wed Dec 08 2010 11:28:31 GMT+0000 (UTC)
check the log/catalina.out in your tomcat directory. it should give you some details as to what the problem is.
by chrisumbel on Sun Dec 12 2010 01:37:05 GMT+0000 (UTC)
The remote server returned an error: (400) Bad Request.
by syed on Wed Mar 09 2011 07:46:57 GMT+0000 (UTC)
Dear chrisumbel,

I had an Error
The remote server returned an error: (400) Bad Request.

Can you help me to solve this ..
by Syed Abdul Kather on Wed Mar 09 2011 07:48:53 GMT+0000 (UTC)
It's just a shame that the docs of SolrNET leave a lot to be desired. A docs for the start.

Any idea how could I specify a several solr servers in case one goes down? Preferably without having to include yet another dependency on a yet another dependency injection library. I've got NInject already and do not want to infest the project with more libraries than strictly necessary :-(
by Jenda on Thu Mar 10 2011 18:02:00 GMT+0000 (UTC)
Add a comment
Name
E mail (Private)
URL
Follow Chris
RSS Feed
Twitter
Facebook
CodePlex
github
LinkedIn
Google