Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NEST mapping of Dictionary<string,object>

Im trying to use NEST and can´t figure out how to use it together with this class

public class Metric {   
    public DateTime Timestamp { get; set; }     
    public Dictionary<string,object> Measurement { get; set; }  
}

How do i use the new fluent mapping with a class like this?

Im planning to use i like this:

var mesurements = new Dictionary<string, object>();
mesurements["visits"] = 1;
mesurements["url"] = new string[] {"/help", "/about"};

connection.Index(new Metric() {
      Timestamp = DateTime.UtcNow, 
      Measurement = mesurements
});

Will it be possible to write a query against the dictionary? If I wanted to get all Metrics from yesterday with a mesurenemt with a key name "visits", how will that look like ?

like image 924
guidmaster Avatar asked Jan 05 '13 22:01

guidmaster


1 Answers

You don't have to use mapping, you can rely on elasticsearch's schemaless nature really well in this case.

The json serializer will write that out as:

{
    "timestamp" : "[datestring]",
    "measurement" : {
        "visits" : 1,
        "url" : [ "/help", "/about"]
    }
}

You can query for the existence of the "measurement.visits" field like so using NEST.

var result = client.Search<Metric>(s=>s
    .From(0)
    .Size(10)
    .Filter(filter=>filter
        .Exists("measurement.visits")
    )
);

result.Documents now hold the first 10 metrics with a visits key in the Measurement dictionary.

If you do want to explicitly map possible keys in that dictionary using the new fluent mapping:

var result = client.MapFluent<Metric>(m => m
    .Properties(props => props
        .Object<Dictionary<string,object>>(s => s
            .Name(p => p.Measurement)
            .Properties(pprops => pprops
                .Number(ps => ps
                    .Name("visits")
                    .Type(NumberType.@integer)
                )
                .String(ps => ps
                    .Name("url")
                    .Index(FieldIndexOption.not_analyzed))
                )
            )
        )
    )
);

Remember that we haven't turned off dynamic mapping using this mapping so you can still inserts other keys into your dictionary without upsetting elasticsearch. Only now elasticsearch will know visits is an actual integer andwe dont want to analyze the url values.

since we are not using any typed accessors (The .Name() call is typed to Metric) .Object<Dictionary<string,object>> could be .Object<object> too.

like image 192
Martijn Laarman Avatar answered Oct 17 '22 12:10

Martijn Laarman