computers are cool

mookid on code

How Windsor’s decorators can save your life (almost)

January 18th, 2011 by mookid

Have you ever needed some kind of “master switch” in your application – i.e. some central place to flick a bool, resulting is changed behavior in numerous places?

Recently, we got the requirement that our application could function in two modes: active and passive. In active mode, the application must work like usual, whereas in passive mode, the app must not do anything to the outside world.

In our app, doing stuff to the outside world can be two things:

  • Writing stuff to a bunch of external SCADA systems.
  • Publishing status messages via NServiceBus.

which means that in order to implement passive mode, we need to avoid doing these two things.

Now, since everything in our app is wired by Windsor, and Windsor supports the nifty decorator pattern, implementing this “master switch” was a breeze!

The master switch

First, we implemented something like this to capture the switch itself:

public class MasterSwitch
{
    public bool IsActive { get; set; }
}

which is registered like this:

container.Register(Component.For<MasterSwitch>().Lifestyle.Singleton);

Note th at the switch is a singleton, thus allowing all other services to have the same instance injected. Note also that concurrency is not an issue in our system – if MasterSwitch was to be used e.g. in an ASP.NET MVC application, it would have had a couple of locks in there or something similar.

Intercepting writes to external systems

All external hardware communication goes through an implementation of this interface:

public interface IExternalStuff
{
    void Write(string name, object value);
    object Read(string name);
}

so in order to abort all writes when we’re in passive mode, we added a new implementation of IExternalStuff that looks something like this:

public class ExternalStuffWithMasterSwitch : IExternalStuff
{
    readonly MasterSwitch masterSwitch;
    readonly IExternalStuff externalStuff;
 
    public ExternalStuffWithMasterSwitch(MasterSwitch masterSwitch, IExternalStuff externalStuff)
    {
        this.masterSwitch = masterSwitch;
        this.externalStuff = externalStuff;
    }
 
    public object Read(string name)
    {
        return externalStuff.Read(name);
    }
 
    public void Write(string name, object value)
    {
        if (!masterSwitch.IsMaster) return;
 
        externalStuff.Write(name, value);
    }
}

Note how ExternalStuffWithMasterSwitch depends on IExternalStuff – this is where Windsor gets really cool, because if I remember to register my components in the following order:

container.Register(Component.For<IExternalStuff>()
                                      .ImplementedBy<ExternalStuffWithMasterSwitch>()
                                      .Lifestyle.Transient,
                   Component.For<IExternalStuff>()
                                      .Instance(new ExternalStuffViaSomeWrappedThirdPartyComponent()));

then Windsor is smart enough to resolve the ExternalStuffWithMasterSwitch supplying the next available implementation of IExternalStuff, instead of entering a cycle.

Thus, we have cancelled all writes through IExternalStuff in our entire application with a few lines of extra code.

Avoiding publishing status messages

First, we needed som way to tell if a message was a status message, which was pretty easy – now all our status messages “implement” this marker interface which in turn implements IMessage from NServiceBus:

public interface IStatusMessage : IMessage {}

So, in order to “swallow” all published status messages when we’re in passive mode, we implemented this decorator to IBus:

public class BusDecoratorThatSwallowsPublishedStatusMessages : IBus
{
    readonly MasterSwitch masterSwitch;
    readonly IBus bus;
 
    public BusDecoratorThatSwallowsPublishedStatusMessages(MasterSwitch masterSwitch, IBus bus)
    {
        this.masterSwitch = masterSwitch;
        this.bus = bus;
    }
 
    // (...) quite a few methods up here
 
    public void Publish<T>(T message) where T : IMessage
    {
        if (!masterSwitch.IsActive && message is IStatusMessage) return;
 
        bus.Publish(message);
    }
}

which must be registered before NServiceBus’ own IBus gets registered:

container.Register(Component.For<IBus>()
                      .ImplementedBy<BusDecoratorThatSwallowsPublishedStatusMessages>()
                      .Lifestyle.Transient);
 
NServiceBus.Configure.With()
                   .CastleWindsorBuilder(container)
                   // (...)

I think this is a really cool example on how wiring everything with an IoC container provides some cool hooks in an application, allowing you to modify behavior in an extremely agile and non-intrusive manner.

2010 retrospective and 2011 resolutions

January 2nd, 2011 by mookid

Now that ++year == 2011, and the last remaining effects of New Year’s Mojitos has finally left my brain, I think it is in order to take a look back at 2010 and evaluate a bit, and then maybe come up with some goals for 2011.

2010 retrospective

2010 has been pretty busy for me – check out this list of professional as well as personal activities:

  • My 2nd child was born in February :) .
  • Wrote 34 blog posts spread pretty evenly over the year (except February).
  • Gave two talks on MongoDB in June, two talks on Castle Windsor in November and December, and two talks on NServiceBus in December.
  • Gave two 2-day introductory courses on getting up to speed with C#, .NET, dependecy injection, unit testing, and continous integration.
  • Gave one 1-day course as an introduction to C#, . NET, and WCF.
  • Gave 2 courses on NServiceBus.
  • Spent September and October on paternity leave.
  • Spent most of my other professional time as a development and architecture consultant on the core team of Dong Energy’s smart grid project, PowerHub. We’re controlling a hydro power plant right now at this very moment :) .
  • Participated in two episodes of ANUGCast about MongoDB: Part 1 and part 2.
  • Learned a lot about new and emerging .NET technologies, NoSQL databases, and about architecture in general.

Looking back at all this, I think 2010 has been a little bit too busy – especially since most of the presentations and teaching happened in November and December :) .

2011 resolutions

This is what I’d like to do in 2011:

  • I would like to continue doing all these great things in 2011, because that’s what makes my job alternating and fun, but ideally I would like to spread the activities some more.
  • I would like to start a pet project – i.e. build “something real”.
  • I would like to continue widening my horizon by cheching out non-.NET-stuff, like e.g. MongoDB and Node.js, which I am actually starting to like quite a bit.
  • I would like to continue contributing to OSS – either in a direct manner with code, or indirectly by blogging, tweeting, helping, creating courses, etc.
  • I would like to continue communicating with great people and be inspired.

Actually I should have hightlighted that last bullet – I guess it pretty much sums up my main goal for 2011 :) .

How to loop good

December 28th, 2010 by mookid

…or “Short rant on why C-style for-loops are almost always unnecessary “…

If you’ve been with C# for the last couple of years, your coding style has probably evolved in a more functional direction since the introduction of C# 3/.NET 3.5 with all its LINQ and lambda goodness.

In my own code, I have almost completely dismissed the old C-style for-loop in favor of .Select, .Where etc., making the code way more readable and maintainable.

The readability and maintainability is improved because long sequences for for/foreach and collection-juggling can now be replaced by oneliners of selection, mapping, and projection.

One place, however, where I often see the for-loop used, is when people need to build sequences of repeated objects, or where some variable is incremented for each iteration.

Now, here is a message to those developers: Please realize that what you actually want to do is to repeat an object or map a sequence of numbers to a sequence of objects.

Having realized that, please just implement it like that:

// repeat some object
var repeatedStrings = Enumerable.Repeat("HELLO", 5000);

Same thing goes for sequences of elements where something is incremented:

// map sequence of numbers to objects
var sequenceOfHourObjects = Enumerable.Range(0, 24)
    .Select(hour => new SomeHourObject { Hour = TimeSpan.FromHours(hour) });

There’s just too many for-loops in the world!

Not the same thing, but still somehow related to that, is when people need to collect stuff from multiple properties and ultimately subject each value to the same treatment – please just implement it like that:

// collect stuff and capitalize
var capitalizedStrings = new [] { obj.FirstName, obj.AnotherName, obj.ThirdName }
    .Select(s => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s));

</rant>

How to avoid (unnecessarily) touching the container

December 23rd, 2010 by mookid

…or “How to resolve stuff all over the place” – two appropriate titles for a blog post that shows the solution to a problem you will eventually run into when using an IoC container… if not in your first application, then maybe in the next…

What’s the problem?

Not all applications lend themselves equally well to leveraging an IoC container for resolving stuff. Generally, applications that follow some kind of request-response pattern are easy to adapt to use the container to build objects that handle requests: Just resolve some kind of handler that handles each request.

E.g.: It is trivial to make Castle Windsor resolve/release controllers in an ASP.NET MVC application by implementing a CastleWindsorControllerFactory.

There are applications however, that do not follow this kind of pattern – or at least not as clearly. Take for instance a typical Windows Forms desktop application that looks like this:

public static void Run()
{
    // yield control to winforms event loop...
    Application.Run(new MainForm());
}

An attempt to use the container could look like this:

public static void Run()
{
    using(var container = new WindsorContainer().Install(FromAssembly.This()))
    {
        var mainForm = container.Resolve<MainForm>();
 
        // yield control to winforms event loop...
        Application.Run(mainForm);
 
        container.Release(mainForm);
    }
}

But then one problem remains: How can we make the Windows Forms application use our beloved Windsor Container without resolving the entire world at this point?

E.g. if MainForm at some point needs to show a SubForm, then how do we do that without doing a new SubForm() inside of MainForm, thus tying MainForm directly to the concrete SubForm? (and worse: ruining our ability to unit test MainForm…?)

Let’s try using a service locator

In order to avoid new‘ing up SubForm, we could use a service locator to provide the form to us. Consider this button handler:

void ButtonOpenSubFormClicked(object sender, EventArgs ea)
{
    var form = ServiceLocator.Resolve<SubForm>();
 
    form.Show();
}

That solves the problem, right? Wrong! I mean, now SubForm can have dependencies injected and stuff, but MainForm is tied to a class called ServiceLocator with a static generic method that creates stuff.

That’s pretty hard to unit test, and in the long run this will just prove to be a serious PITA.

How to fix the problem

If we wanted to fix the problem with MainForm and SubForm, we could do it by passing a ISubFormFactory to MainForm like so:

public interface ISubFormFactory
{
    SubForm CreateSubForm();
}
 
public class MainForm
{
    readonly ISubFormFactory subFormFactory;
 
    public MainForm(ISubFormFactory subFormFactory)
    {
        this.subFormFactory = subFormFactory;
    }
}

thus allowing MainForm to instantiate SubForms at will without depending directly on the container. Now on to implement ISubFormFactory:

public class UncoolSubFormFactory : ISubFormFactory
{
    public SubForm CreateSubForm()
    {
        // oh noes not again..!!1:
        return ServiceLocator.Resolve<SubForm>();
    }
}

Now, why is that implementation uncool? There are several reasons, and two of them are: 1) I’m tying myself to a Windsor container somewhere in a static variable in my app, and 2) The implementation is stupid and boilerplate – I need to write one of these every time I need to show a new form… Uncool!

Enter TypedFactoryFacility

Windsor comes with a bunch of facilities in the box, and one of them fits this gap nicely: TypedFactoryFacility.

If TypedFactoryFacility had a tagline it would be either “The missing link!” or “Gimme another chance!” or something like that.

Put shortly, TypedFactoryFacility gives the container the ability to dynamically implement the ISubFormFactory interface from above, thus allowing my code to pull stuff from the container without even knowing it! \o/

In order to do that, I need to start out by registering the facility;

container.AddFacility<TypedFactoryFacility>();

and then I need to register my factory service like so:

container.Register(Component.For<ISubFormFactory>().AsFactory());

Now the container will delegate the call to CreateSubForm() to container.Resolve(), based on the return type of the factory method – nifty!

When working with Windsor, it is very important that everything that has a transient lifestyle gets properly released! – the facility has this capability as well, just implement a method with the following signature on the factory: void Release(SubForm subForm).

Now our MainForm‘s event handler can look like this:

void ButtonOpenSubFormClicked(object sender, EventArgs ea)
{
    var form = subFormFactory.CreateSubForm();
    form.Closed += delegate { subFormFactory.Release(form); };
    form.Show();
}

allowing Windsor to properly take care of decommission concerns, thus properly disposing IDisposables and more.

I hope this post gave an understandable introduction to TypedFactoryFacility. To help some more, I have created a simple Windows Forms application on GitHub that shows how a simple Windows Forms application can implement a simple MVC pattern using Castle Windsor and TypedFactoryFacility.

Comments, questions and suggestions are appreciated :)

What is that module thing again?

December 16th, 2010 by mookid

This is the fourth post in a small series on Node.js. In this post, I will take a look at how the Node.js module mechanism works.

In my previous posts on Node.js, I nonchalantly went ahead and require(...)d something called http – but what was that? And what happened when I did that?

Well, require is one of the few globals when running a Node program, and it is used to import a module. The parameter is a string, which Node uses to look for a file to load.

The simplest usage refers directly to a file relative to the path of the currently running program. E.g., if I have a module residing in a file called importantBizLogic.js in the lib folder beneath my program’s directory, I can include its exports (which I’ll get back to in a moment :) ) like so:

var biz = require('./lib/importantBizLogic');

If I omit the ./, Node will go look for importantBizLogic in each directory in the require.paths array, which is a list of default paths to search for modules.

Let’s see what it contains… Go to a terminal and enter the Node shell:

mogens-heller-grabes-macbook-pro:~ mhg$ node
> require.paths
[ '/Users/mhg/.node_modules', '/Users/mhg/.node_libraries', '/usr/local/lib/node' ]

Great – so that’ s where my global modules reside. Now, what was that export thing again?

Well, that’s related to how importantBizLogic.js is structured… in order to control how the import works, a module must explicitly export stuff – and that can be done like so:

var secretBizConstant = 0.01;
 
exports.calculateStuff = function(numbers) {
    return numbers.a + numbers.b + secretBizConstant;
};

- allowing this module to be imported and used like so:

var biz = require('./lib/importantBizLogic');
 
var result = biz.calculateStuff({a: 4.15, b: 5.42});

Nifty!

Apparently – and I am almost embarrassed that I did not know that – there is a thing called CommonJS, which is an initiative that strives to create a JavaScript standards library – and the require stuff I’ve described here is actually just Node implementating the CommonJS Modules specification. Pretty sweet, actually!

Up and running with Express

December 13th, 2010 by mookid

This is the third post in a small series on Node.js. In this post, I will take a look at how to get up and running with Express.

Let’s get Express installed – first, let’s install NPM – a package manager for Node:

curl http://npmjs.org/install.sh | sh

That was easy. Now, Express can installed like this:

npm install express

Too easy!

Now, let’s create a simple app like we did the last time:

cd ~
mkdir Projects/HelloExpress
cd Projects/HelloExpress
mate app.js

Punch in the following few lines:

var express = require('express');
var app = express.createServer();
 
app.get('/', function(req, res){
    res.send('Hello Express!');
});
 
app.listen(3000);

and run the app from the terminal like so:

node app.js

and navigate to http://localhost:3000 – on my machine it looked like this:
Hello Express

That was easy. See how the API pretty much resembles Node’s builtin HTTP server, except it adds routes into the mix!

Now, in order to build a web site we need some kind of view engine to help generate some HTML for us. I have used Haml a couple of years ago, and I really liked it… and luckily, some nice people have made Haml available to Node apps, so let’s try installing that:

npm install haml

Now we configure Express by punching in the following stuff in the app:

 
app.configure(function() {
	app.set('view engine', 'haml');
	app.use(express.staticProvider(__dirname + '/public'));
	app.use(express.bodyDecoder());
});

As you can see, I tell Express to use Haml as the default view engine. Moreover, I configure Express to serve static content from the /public folder in my app dir, and then I install the bodyDecoder middleware which will parse incoming posts and make posted values available in req.body.

Now, let’s alter our action to render a view:

app.get('/', function(req, res){
    var locals = {message: 'Express + Haml!!!!'};
    res.render('index', {locals: locals});
});

and now create two files, layout.haml and index.haml in the /views folder. Mine look like this – /views/layout.haml:

!!!
%html
  %head
    %title Hello Express + Haml!
  %body
    = body

and /views/index.haml:

%p
  Hello 
  = message

Now, let’s go to the terminal and node app.js and navigate to http://localhost:3000 – on my computer it looks like this:
Hello Express + Haml

As you can see, view models can be handed to the view via the locals object.

This was some basic web app stuff – only thing missing is some way to persist data, so next time I will take a look at how to get my Mongo on…

Getting started with Node.js

December 9th, 2010 by mookid

This is the second post in a small series on Node.js. In this post, I will take a look at how to get started and run the ubiquitous “Hello world” sample.

First, create a directory somewhere and Git clone Node… I did it like this:

cd ~
mkdir src
cd src
git clone git://github.com/ry/node.git

Then, build and install Node like this:

./configure
make
make install

If you get permission errors during the last step, you might need to do a

sudo chown -R $USER /usr/local

to grant yourself ownership of everything beneath /usr/local. Note however, that this should probably only be done if the machine is your own personal machine.

Now, try typing node -v in the terminal… I got this:

v0.3.2-pre

Now, let’s finish this post by creating a Node app like so (using TextMate or whatever you prefer):

cd ~
mkdir Projects
mkdir Projects/HelloWorld
cd Projects/HelloWorld
mate app.js

Punch in the following few lines:

var http = require('http');
 
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
 
console.log('Server running at http://127.0.0.1:8124/');

and go the terminal again and type

node app.js

which yields

Server running at http://127.0.0.1:8124/

Now, when I navigate to http://localhost:8124 I get this:

Node.js HTTP Hello World

Nifty, huh?

In the next post, I will see if I can get up and running with Express – a simple but powerful Sinatra-like web framework for Node.

I want to learn Node.js

December 6th, 2010 by mookid
Preface

More than three years ago, I watched a couple of videos with Douglas Crockford that changed my view on JavaScript completely!

I must admit that I too used to consider JavaScript a toy language, somehow inferior to “real programming languages” like Java and C#.

This view was of course induced by the sheer amount of JavaScript crap code available to copy/paste from the web, almost always operating on an equally crappy non-standards compliant DOM implementation in some crappy browser – but after watching those videos I actually began to understand that JavaScript was a pretty cool and powerful language.

Some time after, Crockford released JavaScript: The Good Parts which I immediately read, and at that time I remember saying to one of my colleagues: “I think it would be cool to build large systems in JavaScript”.

At that time, stuff like Rhino was around, but I had never heard of anyone actually using it, and executing JavaScript on the JVM by compiling JavaScript into Java into bytecode didn’t sound sexy at all to me.

Today

Recently, however, I have somehow come across Node.js at different occasions, and I have really been meaning to check it out. If you don’t know what Node is about, I can quote the homepage: Node is “Evented I/O for V8 JavaScript.”

That’s right! Let’s break that down:

  • Evented: There’s only one thread executing in a Node process, high throughput is achieved by doing asyncronous I/O, queueing callbacks to be executed upon completion.
  • I/O: Not usually what JavaScript is used for, but this covers the fact that Node has APIs that treat the file system and TCP and HTTP as first class citizens.
  • V8: The JavaScript is executed by the V8 JavaScript Engine that Google in Aarhus built for Chrome.

As an example, there’s the ubiquitous code sample that you’ll see everywhere – opening a HTTP server in Node:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');

As you can see, Node has a nice and thin API for working with HTTP, and as I envy Rubyists of having Rack and Sinatra, and as I am interested in how web frameworks work in general, this code sample has continued to spark my interest.

Therefore, in order to push myself through learning more about it, I have decided to see if I can write a couple of blog posts on Node.js. I will try to cover the necessary topics to develop a simple web app, and I expect to come across more or less of the following:

  • Acquiring Node.js and running a “Hello world” script. Can’t do anything without having done this.
  • Basic Node stuff, like how to structure code into files/modules/whatever and whatnot.
  • Bringing in external, possibly native libraries.
  • Building a web app, possibly with Express – a simple web framework for Node.
  • Persisting some data, probably using node-mongodb – a MongoDB driver for Node.
  • Unit testing my app – probably with the built-in assert API.
  • Hosting my app – probably with Nginx as a router and load balancer.

Wow! – that was a lot of words and almost no code… I promise that my next posts on Node will have more code in them.

Assuring that those IWantToRunAtStartup can actually run at startup

November 25th, 2010 by mookid

When building NServiceBus services based on the generic host, you may need to do some stuff whenever your service starts up and shuts down. The way to do that is to create classes that implement IWantToRunAtStartup, which will be picked up by the host and registered in the container as an implementation of that interface.

When the time comes to run whoever wants to run at startup, the host does a

container.ResolveAll<IWantToRunAtStartup>()

to get all the relevant instances (or something similar if you aren’t using Windsor…).

If, however, one or more instances cannot be instantiated due to missing dependencies, you will get no kind of warning or error whatsoever! 1 This means that the service will silently ignore the fact that one or more IWantToRunAtStartups could not be instantiated and run.

In order to avoid this error, I have written a test that looks somewhat like this:

[Test]
public void WhoeverWantsToRunAtStartupCanActuallyRun()
{
  var container = new WindsorContainer();
 
  PerformTheUsualRegistration(container);
 
  var typesThatWantToRun = from type in typeof (MyService.EndpointConfiguration).Assembly.GetTypes()
                         where typeof(IWantToRunAtStartup).IsAssignableFrom(type) 
                             && !type.IsAbstract && !type.IsInterface 
                         select type;
 
  ManuallyRegister(container, typesThatWantToRun);
  RegisterFakeBus(container);
 
  var typesThatCouldRun = container.ResolveAll<IWantToRunAtStartup>().Select(c => c.GetType());
  var typesThatCouldNotRun = typesThatWantToRun.Except(typesThatCouldRun);
 
  if (typesThatCouldNotRun.Any())
  {
    Assert.Fail(string.Join(Environment.NewLine + Environment.NewLine,
          typesThatCouldNotRun.Select(t => GenerateErrorDetailsFor(t, container)).ToArray()));
  }
}
 
string GenerateErrorDetailsFor(Type type, IWindsorContainer container)
{
  // first, register the class as itself if is has not already been done
  if (!container.Kernel.HasComponent(type))
  {
    container.Register(Component.For(type).Named(type.name + " that wants to run"));
  }
 
  // next, make Windsor throw an exception with all the nasty details...
  var exceptionText = "";
 
  try
  {
    container.Resolve(type);
  }
  catch (HandlerException e)
  {
    exceptionText = e.Message;
  }
 
  return string.Format(@"Class: {0}
 
Reason:
 
{1}", type.Name, exceptionText);
}
 
void PerformTheUsualRegistration(IWindsorContainer container)
{
  container.Install(FromAssembly.Containing<MyService.EndpointConfiguration>());
}
 
void ManuallyRegister(IWindsorContainer container, IEnumerable<Type> typesThatWantToRun)
{
  container.Register(typesThatWantToRun
                        .Select(t => Component.For<IWantToRunAtStartup>().ImplementedBy(t))
                        .ToArray());
}
 
void RegisterFakeBus(IWindsorContainer container) 
{
  container.Register(Component.For<IBus>().Instance(MockRepository.GenerateMock<IBus>());
}

I admit that the code is kind of clunky even though I distilled the interesting parts from some of the plumbing in our real test… moreover, our real test is iterating through all the possible configurations our container can have – one for each environment – so you can probably imagine that it’s not pretty :)

But who cares??? The test has proven almost infinitely useful already! Whenever something that wants to run at startup cannot run at startup, TeamCity gives us error messages like this:

Class: RunSomething
 
Reason:
 
Can't create component 'RunSomething that wants to run'  as it has dependencies to be satisfied. 
RunSomething that wants to run is waiting for the following dependencies: 
 
Services: 
- OneOfOurProjects.Api.ISomethingElse which was not registered.
  1. At least this is the case when using Castle Windsor – I don’t know if this is also the behavior of other IoC containers… Maybe someone can clarify this…?

Fun with RavenDB 3

November 8th, 2010 by mookid

This is the third post in a small series about RavenDB – a document database in .NET. I will try to touch the same areas as I did in my series on MongoDB, possibly comparing the two where I see fit.

Now, this time we will take a look at some more querying…

Introduction

After having chewed a bit on the concept of map/reduce queries from doing my MongoDB series, I am actually beginning to see the beauty of this kind of query – and of course RavenDB supports them as well, because it is currently the only sane way to structure aggregate queries in distributed databases.

All of RavenDB’s queries are actually map/reduce queries, but if you don’t supply a reduction function, the reduction is trivial, as every document is emitted in its entirety.

Now, let’s try specifying our own reduction function….

Simple map/reduce query

But first we’ll start out by stuffing some data in the DB:

using (var session = documentStore.OpenSession())
{
    session.Store(new Order
                        {
                            Items =
                                {
                                    new Item {Name = "beer", Amount = 12},
                                    new Item {Name = "peanuts", Amount = 3},
                                    new Item {Name = "cashew nuts", Amount = 4},
                                }
                        });
 
    session.Store(new Order
                        {
                            Items =
                                {
                                    new Item {Name = "beer", Amount = 6},
                                    new Item {Name = "just nuts", Amount = 8},
                                    new Item {Name = "peanuts", Amount = 6},
                                    new Item {Name = "cashew nuts", Amount = 2},
                                }
                        });
 
    session.Store(new Order
                        {
                            Items =
                                {
                                    new Item {Name = "beer", Amount = 5},
                                }
                        });
 
    session.SaveChanges();
}

Now, in order to aggregate each Item by name, summing up the amounts, let’s construct the following index:

 
public class AggregateAmountsPerItem : AbstractIndexCreationTask
{
    public override IndexDefinition CreateIndexDefinition()
    {
        return new IndexDefinition<Order, ItemAggregate>
                    {
                        Map = orders => from order in orders
                                        from item in order.Items
                                        select new {item.Name, item.Amount},
                        Reduce = items => from item in items
                                            group item by item.Name into i
                                            select new {Name = i.Key, Amount = i.Sum(x => x.Amount)}
                    }.ToIndexDefinition(DocumentStore.Conventions);
    }
}

Note how this way of structuring the map/reduce differs from MongoDB and CouchDB where the map operation decides which value to aggregate on by emitting it as the key – in RavenDB, this decision is made in the reduce function.

Note also that I need to create a type, ItemAggregate, that is used to tell which fields the reduce function should expect as input. It is important that this type’s fields correspond to those emitted from the map function, or else the serialization will fail silently, yielding no results.

Now, let’s execute the index creation like so:

IndexCreation.CreateIndexes(typeof (AggregateAmountsPerItem).Assembly, documentStore);

and now I am ready to query the index:

using(var session = documentStore.OpenSession())
{
    var amountsPerItem = session.Query<ItemAggregate>(typeof(AggregateAmountsPerItem).Name);
 
    foreach(var amountPerItem in amountsPerItem)
    {
        Console.WriteLine("{0}: {1} pcs", amountPerItem.Name, amountPerItem.Amount);
    }
}

which yields the following results:

Executing query '' on index 'AggregateAmountsPerItem' in 'http://localhost:8080'
Query returned 4/4 results
beer: 23 pcs
peanuts: 9 pcs
cashew nuts: 6 pcs
just nuts: 8 pcs

and that was pretty much what I expected.

That was a quick look at map/reduce queries in RavenDB. I’m sure there’s no end to the fun you can have with this kind of stuff, but I have yet to use map/reduce for anything in a real project, so I can’t really comment further on those.

« Previous Entries Next Entries »