0

This is my document:

[ElasticsearchType(Name = "MyDoc")]
public class MyDoc: Dictionary<string, object>
{
    [String(Store = false, Index = FieldIndexOption.NotAnalyzed)]
    public string text { get; set; }
}

As you can see, it inherits from Dictionary<string, object> so I can dinamically add fields to it (this is a requirement to make aggregation work)

Here I store the mapping:

client.Map<MyDoc>(m => m.Index("myindexname").AutoMap());

Now I create a new record and store it:

 var rec= new MyDoc();
 rec.Add("id", "mystuff");
 rec.text = "mytext";
 client.Index(rec, i => i.Index("myindexname"));
 client.Refresh("myindexname");

The record get actually stored but the text field is not persisted. Here the JSON back from ElasticSearch 2.0

{
"_index": "myindexname",
"_type": "MyDoc",
"_id": "AVM3B2dlrjN2fcJKmw_z",
"_version": 1,
"_score": 1,
"_source": {
"id": "mystuff"
}
}

If I remove the base class from MyDoc the text field is stored correctly but obviously the dictionary content is not (I also need to remove the .Add() bit as the document doesn't inherit from a Dictionary).

How to store both the text field and the dictionary content?

Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159

1 Answers1

1

Sorry i wrote wrong suggestion in my previous post so i deleted it. I think issues is actually in serialization since your base class is Dictionary

I would do two things first try to serialize your object to see output string i am pretty sure that text is ignored.

Second i would change class to following

public class MyDoc : Dictionary<string, object>
    {
        public string text
        {
            get
            {
                object mytext;
                return TryGetValue("text", out mytext) ? mytext.ToString() : null;
            }
            set { this.Add("text", value);}
        }
    }

PS. As i thought issue is on c# side since you inherit from dictionary,

var rec = new MyDoc();
rec.Add("id", "mystuff");
rec.text = "mytext";
//Text2 is property         public string text2 { get; set; }
rec.text2 = "mytext2";
var test = JsonConvert.SerializeObject(rec); //{"id":"mystuff","text":"mytext"}
Vova Bilyachat
  • 18,765
  • 4
  • 55
  • 80
  • Thanks. Looks like a wrapper which stores the text using the dictionary. It's fine ok but I was looking for the reason why the normal fields are not stored. It must be possible to store both the normal fields and the dictionary content – Gianluca Ghettini Mar 02 '16 at 11:35
  • Because you are inheriting from dictionary. – Vova Bilyachat Mar 02 '16 at 11:37
  • Ok but why if I inherits from dictionary the other fields are ignored. Is this a basic rule hardwired into elasticsearch or what? – Gianluca Ghettini Mar 02 '16 at 11:40
  • Its releated to C# it has nothing to do with elasticsearch since c#, serialize and then send to ES as a string. – Vova Bilyachat Mar 02 '16 at 11:41
  • Try to do the following http://stackoverflow.com/questions/14893614/how-to-serialize-a-dictionary-as-part-of-its-parent-object-using-json-net I am not sure if it would work since i did not tired that – Vova Bilyachat Mar 02 '16 at 11:42
  • This is default JSON.Net behaviour; if the type being serialized implements `IEnumerable`, then it will be serialized as a collection and hence other properties that are not iterated/enumerated will not be included. You could write a custom json converter to handle this too, but this answer ensures that an item with the key `text` cannot be added to the dictionary in addition to the `text` property so is a good way to handle this – Russ Cam Mar 02 '16 at 12:23