Thursday, October 23, 2014

Using SolrNet (0.4.0.2002) and AutoMapper...

If you're using Solr and you prefer to use .Net, then SolrNet is a great way to go. It's easy to use whether your indexing documents, querying for documents, or both.

Here is an example using Solr 4.10.1, SolrNet 0.4.0.2002, and AutoMapper

I installed Solr 4.10.1, and used the default example "collection1" core for this example. 

I created a POCO for the example and cleverly named it SolrDoc. I only bothered with a few of the values that are defined in the schema used in the collection1 core:

public class SolrDoc
{
    [SolrUniqueKey("id")]
    public string Id { get; set; }

    [SolrField("sku")]
    public string Sku { get; set; }

    [SolrField("name")]
    public string Name { get; set; }

    [SolrField("cat")]
    public List Categories { get; set; }

}

And created another POCO to act as a domain object (only to show how you can map from the Solr document), and named it SolrItem:


public class SolrItem
{
    public string Identifier { get; set; }
    public string Sku { get; set; }
    public string Name { get; set; }
    public List Cats { get; set; }
    public override string ToString()
    {
        var sb = new StringBuilder(
                 string.Format("Identifier: {0}, SKU: {1}, Name: {2}", 
                                Identifier, Sku, Name));
        if (Cats != null)
        {
            sb.Append("\nCategories:");
            foreach (var category in Cats)
            {
                sb.Append(string.Format("\n\t{0}", category));
            }
        }
        return sb.ToString();
    }
}

The following code isn't necessary for use with Solr, but it is necessary for creating the AutoMapper mapping between SolrDoc and SolrItem. Perhaps you won't need to map your Solr documents to some other contract object, but if you do have that need then AutoMapper is easy to use. 

One way that AutoMapper can be used is to map between public and private views of data. As an example, you might have an API that allows users to view either detailed or summary user info. Your private model of the user data can have all user information and you can have AutoMapper map the user info to summary or detailed user info objects that are returned to the user. I included the AutoMapper usage as a way to show that you can easily get the Solr documents and then map them to whatever form you might need.

Here is the code that configures AutoMapper's source to destination mapping.


public static void InitMappings()
{
    Mapper.CreateMap()
        .ForMember(dest => dest.Cats, opt => opt.MapFrom(src => src.Categories))
        .ForMember(dest => dest.Identifier, opt => opt.MapFrom(src => src.Id));

}

Here is the code that indexes a document into Solr, and then queries Solr for all documents. The foreach loop is where the SolrDoc is mapped to a SolrItem.


static void Main(string[] args)
{
    // Set up the automapper mapping
    InitMappings();
        
    // Point to the Solr server that was started using the Solr example
    // of "java -jar start.jar"
    Startup.Init<SolrDoc>("http://localhost:8983/solr/collection1");

    // Get an instance of the Solr service that will map Solr documents to 
    // a POCO of type SolrDoc
    var solr = ServiceLocator.Current.GetInstance<ISolrOperations<SolrDoc>>();

    // Create a SolrDoc to index into Solr
    var doc = new SolrDoc
    {
        Id = Guid.NewGuid().ToString(),
        Name = "Some SolrDoc",
        Sku = "Some_Sku",
        Categories = new List {"cat1", "cat2", "cat3"}
    };

    // Index and commit the doc
    solr.Add(doc);
    solr.Commit();

    // Query for all documents
    var results = solr.Query(new SolrQueryByField("id", "*"));

    // Loop through all results
    foreach (var result in results)
    {
        var solrItem = Mapper.Map<SolrItem>(result);
        Console.WriteLine(solrItem);
    }
}

Saturday, October 11, 2014

Testing XSLT changes can be slow if you don't have the right tools

There are probably 50 million tools out there for writing XSLT and viewing the output. I have been in the habit of using a command line app that would take a path to the XSLT file, the source xml file, and a target output file. It worked good enough since I don't usually have to do a lot of XSLT. I just started doing changes on a project that uses XSLT to transform data into XML that can be used to index into a Solr instance, and there are quite a few fields that I need to format in a variety of ways. I was using the simple command line app to view the output, but it was getting a bit tedious.  I was wishing I had something more like IntelliJ - something that would show me the output right away, and it dawned on me that all I needed would be three text boxes and a timer control to get what I wanted.  

Introducing the incredibly named XsltTester. It's pretty basic, and I'm sure that there are existing free tools that do the same thing. However, this took just 30 minutes or so and it was fun to put together.

Here is a link to the project on BitBucket: https://bitbucket.org/lee_wallen/xslttester

Here are a few views of the app:


New icons and buttons.


Example with XML and invalid XSL.

Example with XML and fixed XSL but wrong output.

Example with XML, fixed XSL and fixed output.