Try our conversational search powered by Generative AI!

Reloading Custom Data From Find Index

Vote:
 

Hi guys, for a very complex search we've been indexing some custom .NET objects which we need to search on and to reload back as .NET objects. The searching works fine using the following guide https://world.episerver.com/documentation/developer-guides/find/NET-Client-API/Customizing-serialization/Including-fields/ but we are having problems re-loading the data. As an example I've thrown a simple example up on Alloy for replication.

Firstly on the ArticlePage type I have added the following extra properties/methods. The GetSomeField() should just be returning the standard Name field back.

[Ignore]
public string FindTestField { get; set; }
        
public string GetSomeField()
{
   return Name;
}

public void SetSomeField(string value)
{
   FindTestField = value;
}

We then have an initilization module with the following simple code

[ModuleDependency(typeof(IndexingModule))]
public class FindInitialization : IInitializableModule
{
   /// <inheritdoc />
   public void Initialize(InitializationEngine context)
   {
      SearchClient.Instance.Conventions
      .ForInstancesOf<ArticlePage>()
      .IncludeField(x => x.GetSomeField(),(x, value) => x.SetSomeField(value));
   }

   /// <inheritdoc />
   public void Uninitialize(InitializationEngine context)
   {
   }
}

Episerver Find is indexing this GetSomeField as expected with the correct data, however when doing a search with the following code

var eventPages = SearchClient.Instance.Search<ArticlePage>().GetContentResult();
var firstaPage = eventPages.Items.First();
var findFullname = firstaPage.FindTestField;

The findFullname variable is null? This is a simple example of what we're trying to do, in our real solution this is an IEnumerable of .NET objects but how to we re-serialize the objects back somewhere in the model. I've been looking at the code for the IncludeFieldCustom and Episerver own indexing of objects and can't figure it out.

#202067
Edited, Mar 13, 2019 10:44
Vote:
 

I'm struggelig to understand what you are trying to solve :)

What you add to the index is the GetSomeField field which will be a string field in the index:

#202107
Mar 14, 2019 12:24
Vote:
 

In our real scenario which is too complex to post we have a load of content items that have an IEnumerable<> of models that are indexed in Find. Most of these content items the collection is an array of about 50-60 of these custom index items. These are use in a faceted search filter which works fine in find but we need when getting these content items back to have these custom models re-serialized from the find (how it works when you do it directly using elastic or vulkan). Otherwise when you call the method in .NET to access this custom method/property .NET will reload all the data again via the C# logic.

For example in the above post as you said the property GetSomeField$$string exists in the index and I can use the Find .NET API to query against it

var eventPages = SearchClient.Instance.Search<ArticlePage>().GetContentResult();

However if after loading these article pages I try to access GetSomeField the c# code that returns name is going to execute again. In a complex scenarioes of loading some custom data this causes large amounts of overhead. 

From the example in world as attached the second method on the IncludeField is supposed to allow you to handle the object coming back from find. Ergo that's what I was trying to use.

Under the covers I've looked in to find and there's a lot of converters and convensions used for serializing the objects but in my simple example I can't get anything to work.

#202139
Mar 15, 2019 9:59
Vote:
 

Does it help to make the fields and methods virtual? Just shooting from my hip here...

#202146
Mar 15, 2019 16:13
Vote:
 

It's okay I've had some conversations with Episerver support now. The issue is the way .GetContentResult() works, under the covers when it's getting back the data from find it's actually just getting back the ContentReference of the item and fully reloading the data from the Content APIs. 

Another method .GetResult() instead serializes the data back directly from the find data in to the correct object.

This is all quite odd and seems to be a work around on loading IContent based data with MetaFields back without having issues of reloading from Find so instead just reloading the data. Sadly .GetResult() blows up if you use anything IContent inherited.

We're close we think to getting it working by indexing our own custom model for this data and then using .GetResult() instead. 

As I said it's odd behaviour, you'd think for performance you wouldn't want to reload everything. Episerver have put an R&D ticket in to try and figure out if there's a way to rework this to be more sensible.

#202147
Edited, Mar 15, 2019 16:20
Vote:
 

Hi Scott, 

You could also keep using your ArticlePage type, but instead of returning this back with GetContentResult() use projections to return back either an anonymous type or another model back from Find. This would result in a call to GetResult() so you won't get this type of issue but you can still search across your Article Pages. 

#202233
Mar 20, 2019 11:13
Vote:
 

Dammn this would have been lovely to know before rebuilding everything or if Episerve support had told us this...haha. 

I've covered it all in my blog https://world.episerver.com/blogs/scott-reed/dates/2019/3/episerver-find---performance-reloading-custom-data-and-getcontent-vs-getcontentresult/ I'll update it to include your suggestion.

#202235
Mar 20, 2019 11:19
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.