-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support extending NEST types by deriving and implementing properties #3655
Comments
We are currently running into this issue: we have a custom token filter that has an extra string property, which does not get serialized by the new serializer. |
Not with the high level client call at the moment, @joostPieterse. It's still possible to send the request as an anonymous type with the low level client, although I appreciate it is more work. With the change in #4032, it will be good to revisit this. to see if we can make this easier in the high level client again. |
We are experiencing similar problem. We index documents, that implement ICustomTypeDescriptor, but since the utf8json upgrade, the serializer is not respecting it. It just serializes the public properties, which generates completely wrong json and causes the index call to fail. Do you have any plans on fixing this? Before the utf8json upgrade it worked perfectly. |
We upgraded to 7.5 (latest at this point), but sadly the problem is still present. We have an object, implementing ICustomTypeDescriptor, but the properties sent by the ElasticClient are the ones from the object type, not the object itself. We need this object to have dynamic properties. Is there a workaround for this? |
@bonny-bonev would you be able to provide some more detail on which types you're deriving from? Might be easiest to see what you're doing in a prior NEST version that works |
@russcam - In the previous version we used (5.5) this worked perfectly. We have an object, implementing ICustomTypeDescriptor and extending DynamicObject, but if this is not supported, we can implement any other interface that is used to retrieve the properties of our object. Basically we have an object, holding a dictionary and returning some or all of the values from the dictionary as it's properties using the mentioned ICustomTypeDescriptor interface. After the serializer change in Elasticsearch to utf8json this stopped working and the client is getting all of the object properties disregarding the ICustomTypeDescriptor interface. We can implement any interface, or use a marker attribute, but I can't find any information on how to do this. |
It's probably easier to see what you have in code @bonny-bonev. Would you be able to provide a succinct, but complete, example? Specifically, I'm interested in seeing which NEST types are derived from, so that I can investigate a way forward. |
We are not inheriting any NEST type. The object we are sending looks something like this: using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
public class MyCustomDocument : DynamicObject, ICustomTypeDescriptor
{
public string TestProperty {get; set;}
public AttributeCollection GetAttributes()
{
return new AttributeCollection(null);
}
public string GetClassName()
{
return null;
}
public string GetComponentName()
{
return null;
}
public TypeConverter GetConverter()
{
return null;
}
public EventDescriptor GetDefaultEvent()
{
return null;
}
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
public object GetEditor(Type editorBaseType)
{
return null;
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return new EventDescriptorCollection(null);
}
public EventDescriptorCollection GetEvents()
{
return new EventDescriptorCollection(null);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return this.GetPropertyDescriptorCollection();
}
public PropertyDescriptorCollection GetProperties()
{
return ((ICustomTypeDescriptor)this).GetProperties(null);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
private PropertyDescriptorCollection GetPropertyDescriptorCollection()
{
var propertyNames = new List<string>() { "propName" }; // There is custom mechanism for getting the current properties for the document, but for the example static list is sufficient.
var properties = new PropertyDescriptor[propertyNames.Count];
for (int i = 0; i < propertyNames.Count; i++)
{
// We use custom property descriptor, but just comment this line. The idea is that the ElasticSearch client is not even calling this method to get the object properties.
// We need to have extensibility to specify the object properties dynamically for the specific instance that we are sending for indexing.
properties[i] = new CustomPropertyDescriptor(propertyNames[i]);
}
return new PropertyDescriptorCollection(properties);
}
} The problem is that the client is not indexing the dynamic properties of the object, but just the static properties of the class "MyCustomDocument". |
OK, I think I see what the problem is here, @bonny-bonev. This is quite a different issue to the one to which this issue relates, though; the issue you describe is related to documents you control that you need to index, whereas this issue is related to deriving types from NEST types in order to include additional properties. It looks to me like var defaultIndex = "default_index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool, JsonNetSerializer.Default)
.DefaultIndex(defaultIndex);
var client = new ElasticClient(settings); I tried to write an example to demonstrate, but I don't know what |
Thank you. There is no need to write example, I will try this and get back to you. Thanks again for your time - it seems that you understand the issue, so I hope the solution will work. |
Hi again. The solution you suggested seems to work for us at this point. Thank you very much! |
I'm going to close this issue and open a new specifically to track extending token filters #3655 (comment) |
With the move to utf8json in #3493, the serialization of NEST types is strict, serializing only those properties specified on implemented interfaces in many places. For example,
PropertyFormatter
only serializes theI*Property
interface members:elasticsearch-net/src/Nest/Mapping/Types/PropertyFormatter.cs
Lines 97 to 192 in f3ec719
With such strictness, it is not currently possible to derive a type from a NEST type, add additional properties, and have those properties serialized by the internal serializer. This is demonstrated in
InjectACustomIPropertyImplementation()
elasticsearch-net/src/Tests/Tests/ClientConcepts/HighLevel/Serialization/ExtendingNestTypes.doc.cs
Lines 53 to 97 in e2b7f75
utf8json is able to support this feature through using the fallback formatter,
DynamicObjectTypeFallbackFormatter
,exposed by resolving aIJsonFormatter<object>
, which internally inspects the type and generates a custom serialization method for it, caching it in aThreadsafeTypeKeyHashTable<KeyValuePair<object, SerializeMethod>>
. This path looks like it would be a plausible way to support extending NEST types but requires some guarding when serializing Attribute types; when a type to serialize is anAttribute
type, the walking of properties performed byMetaType
traverses down to a framework enum type with multiple members with the same undelying value, which trips up theEnumFormatter
. For an Attribute type, this walking should not be performed.The text was updated successfully, but these errors were encountered: