[Solved] Help with Examine RangeQuery for Custom D...
# help-with-umbraco
u
Hello, I'm working on an Umbraco application for a client (version 13) and am encountering issues while using Examine to perform a RangeQuery on a custom date field. My field, named
searchableDateField
, doesn't seem to be indexed in the same manner as Umbraco’s built-in createDate field, despite my efforts to convert
searchableDateField
to the DateTime format ticks, which I believe is also used for
createDate
. When I execute the following query:
query.And(q => q.RangeQuery(new[] { "searchableDateField" }, startDate, endDate, minInclusive: true, maxInclusive: false));
I receive this error message from Examine:
"An error occurred during the search: Could not perform a range query on the field searchableDateField, its value type is Examine.Lucene.Indexing.FullTextType"
Interestingly, when I replace
searchableDateField
with
createDate
, the query works fine and returns the expected results (the documents with a `createDate`between
DateTime startDate
and
DateTime endDate
query.And(q => q.RangeQuery(new[] { "createDate" }, startDate, endDate, minInclusive: true, maxInclusive: false));
I currently save the value of
searchableDateField
in a label in Umbraco as a DateTime (DateTime format Ticks). I have also tried saving the
searchableDateField
in various DateTime formats (both in dateTime labels and fields) and in the compatible types of labels, such as string, BigInt, etc. i could think of and then casting them as DateTime values. However, my results remains the same as described above. The main difference I can think of is that
createDate
exists on all my DocumentTypes, whereas
searchableDateField
does not always exist on all DocumentTypes. If anyone has experience working with custom date fields in Examine and Umbraco and can offer guidance or suggest a solution (even a creative one, as I really want to solve this), I would be very grateful for any tips or advice. Thanks
j
You probably need to specify the indexfield type, you can do this in a file like this:
Copy code
csharp
public class ExternalIndexOptionsOverwrite : IConfigureNamedOptions<LuceneDirectoryIndexOptions>
{
    public void Configure(LuceneDirectoryIndexOptions options) => Configure(string.Empty, options);

    public void Configure(string? name, LuceneDirectoryIndexOptions options)
    {
        if (name?.Equals(Umbraco.Cms.Core.Constants.UmbracoIndexes.ExternalIndexName) is not true) return;
        
        
        options.FieldDefinitions.AddOrUpdate(new FieldDefinition("searchableDateField", FieldDefinitionTypes.DateTime));
    }
}
Then register it in a composer:
Copy code
builder.Services.AddSingleton<IConfigureOptions<LuceneDirectoryIndexOptions>, ExternalIndexOptionsOverwrite>();
u
Thanks will try this
Hey @Jemayn , first off, thank you so much for your assistance. I attempted to implement the solution you suggested, but unfortunately, I'm still facing some issues. It's possible that I'm missing a step or perhaps misunderstanding something. Here's the code I'm working with:
Copy code
// ExternalIndexOptionsOverwrite.cs
using Examine;
using Examine.Lucene;
using Microsoft.Extensions.Options;

public class ExternalIndexOptionsOverwrite : IConfigureNamedOptions<LuceneDirectoryIndexOptions>
{
    public void Configure(LuceneDirectoryIndexOptions options) => Configure(string.Empty, options);

    public void Configure(string? name, LuceneDirectoryIndexOptions options)
    {
     if (!name?.Equals(Umbraco.Cms.Core.Constants.UmbracoIndexes.ExternalIndexName) ?? true) return;
        options.FieldDefinitions.AddOrUpdate(new Examine.FieldDefinition("searchableDateField", FieldDefinitionTypes.DateTime));
    }
}
I've registered the service in my Program.cs:
Copy code
// Examine config service
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IConfigureOptions<LuceneDirectoryIndexOptions>, ExternalIndexOptionsOverwrite>()
And here is how I'm querying using the field in my SearchApi.cs file:
Copy code
DateTime? startDate = searchRequest.StartDate;
DateTime? endDate = searchRequest.EndDate;

query.And(q => q.RangeQuery(new[] { "searchableDateField" }, startDate, endDate, minInclusive: true, maxInclusive: true));
Despite this, I'm still receiving the same error when attempting to search date ranges with the above query:
"An error occurred during the search: Could not perform a range query on the field searchableDateField, its value type is Examine.Lucene.Indexing.FullTextType"
After manually rebuilding Examine indexes If you could help me pinpoint what I might be doing wrong or what I'm missing? It would be greatly appreciated.
m
Did you rebuild your indexes for the content to be reindexed against your altered schema?
you can check it's worked by using the backoffice examine dashboard to find a node with your datetime field.. if it's reindexed it should be a long, otherwise will show as a string rep of your date
j
You may have to restart the site for the new index options to trigger. Also now I am wondering if you are registering the options before Umbraco does so they end up overwriting your change
Try putting the registration in a composer instead
m
Even restarting the site (recycling the app pool) doesn't nec mean a full index rebuild, if it think the index is current it will load the cahced index from disk 🙂
I suggest hitting the rebuild index in the back office.
Copy code
csharp
public class SearchComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
    {
        // Custom Examine configuration
        builder.Services.ConfigureOptions<ConfigureExamineIndexOptions>();
    }
}
aah you are registering a service.. not configuring the umbraco options.. https://docs.umbraco.com/umbraco-cms/reference/searching/examine/indexing#creating-a-configureoptions-class
u
Thanks 🙂 Before my last post I've rebuilt the index in the backoffice and restarted the site (several times 🙂 ), and I can confirm that
searchableDateField
exists Examines external index, but the error still persisted. As a note, I've also added fields such as searchableGeoGraphicalLocations, searchableLabels, and searchableSubjectAreas, which all worked perfectly from the outset without any need for special indexing configurations, so i think it might be related to how examine uses the RangeQuery or perhaps how i use it. Next, I plan to try using a composer to see if it makes any difference. I'm hoping this might provide a different approach to resolve the ongoing issue with date range searches. https://cdn.discordapp.com/attachments/1218085550926331914/1218156128937054329/Screenshot_2024-03-15_at_12.09.52.JPG?ex=6606a34d&is=65f42e4d&hm=e0e489974a674dab98baca5eab90bb1c544d2fd513cda09b88577bd69fc6cca7&
Hello again, Edit: After attempting the solutions you suggested, I am unfortunately still encountering the same error. I'm trying to use my custom date fields for a range query search, but it's not working, where the same query works with Umbraco’s native field "createDate". My data is saved into a label-field of the the Date as a DateTime (dateformat Ticks), and I can confirm that it appears in both my External and Internal indexes. However, when i use my field in the same examine query that works with "createDate" I receive the error: "An error occurred during the search: Could not perform a range query on the field searchableDateField, its value type is FullTextType." This leads me to believe that my indexed field is not being recognized as a DateTime format by Examine. I've have used the DateTime format ticks for my "searchableDateField" in a manner so it would be the same as the built-in createDate field property, ensuring it’s correctly indexed in Examine’s external index. Despite these efforts, I am unable to successfully perform a date range search on this field. Any insights or suggestions on what I might be overlooking or doing incorrectly would be greatly appreciated. Thanks
m
i'm using
query.And().RangeQuery<DateTime>(new[] { expiresAlias }, min: DateTime.Now, max: null);
Just a thought.. you're updating the ExternalIndex Fields in the shared code.. you are searching against the ExternalIndex, and not the internal one? (sorry if that's telling you to suck eggs 😉 )
You won't need to change the analyzer though 😉
u
Thanks a lot! I managed to work it out and got it working (small victory dance!) The main issue was that I assumed a custom field of the type DateTime would also be indexed as DateTime in Examine, which, of course, it was not. After I figured that out, the solution we discussed worked great, but I wouldn’t have gotten there without your help (or at least not today). Big Thanks again to @Mike Chambers & @Jemayn
268 Views