Having worked with Kentico since version 4 I've found many things just come easy now. That is, with the exception of the Lucene syntax used in Kentico's Smart Search. I've heard many people talk about looking into the Lucene data and finding what's actually in there but until a few weeks ago, I've never done it as I've always been able to work through it. Read more to find out how I've resolved an ever mind blowing problem with dates in Kentico's Smart Search.
Problem
Kentico's Smart Search does a great job of what we need for every day searching and if we can't get something to work, someone on the DevNet or the Slack channel will have some sort of workaround for us. BTW, if you're not on the Slack channel AND you're a Kentico Partner, send me a message and I'll get you added. This time the client request was a unique one as the clent had 3 different date fields they were working with and wanted events to display in the smart search results if the event spanned multiple days.
Seems simple enough right? In SQL it would be a pretty simple task but using the Lucene syntax, NOTHING is easy unless you use the syntax a lot and are fluent in it. Here's my setup:
Fields
- StartDate
- EndDate
- SortDate ( this is the exact value of the EndDate if one is entered, otherwise the StartDate)
Smart search index specifically for /Events (cms.event) page types. The use case is when we have an event which spans more than one day, it needs to show in the search results until the end date has past.
Solution - Luke for Lucene!
I've never looked at or into the Lucene data which is created by Kentico when I created an index. I figured today was the day this would happen. After downloading Luke and running the .jar file, I was able to see so much info and evaluate the Lucene data. It even allowed me to enter in the syntax I thought was right and see what was actually parsed (and data returned).
So I know dates can be a hassle using Lucene but Kentico has a nice macro which handles converting a regular DateTime object into a Lucene date object:
{%ToSearchDateTime(YourDateTimeObject)%}
Using the above macro with another macro will allow you to get the current day at midnight by using the .ToShortDateString() method.
{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%}
Using the above, got me the starting date of my BETWEEN clause. For the end date, I simply added 3 years (hack) to get the ending date. So my initial syntax was:
+startdate:[{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%} TO ToSearchDateTime(CurrentDateTime.AddYears(3).ToShortDateString())]
Next I needed to look at another field to find out if that field was between today and 3 years from now. Pretty simple to add this in BUT the OR clause wasn't working for me.
+startdate:[{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%} TO ToSearchDateTime(CurrentDateTime.AddYears(3).ToShortDateString())] OR +enddate:[{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%} TO ToSearchDateTime(CurrentDateTime.AddYears(3).ToShortDateString())]
When I parsed my above query in Luke it appeared to work but had a few extra records. After a bit more looking around in Luke, I found what the query above was actually "parsed" out vs. how it was "rewritten"to be.

Shows the parsed query

Shows the ACTUAL syntax which was parsed out AND rewritten
After a bit more playing around with this, because I was intrigued, the final macro I had to check dates in two fields between specific dates was:
+(ConstantScore(eventdate:[{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%} TO ToSearchDateTime(CurrentDateTime.AddDays(900).ToShortDateString())]) ConstantScore(eventenddate:[{%ToSearchDateTime(CurrentDateTime.ToShortDateString())|(user)bkehren|(hash)3c34d64f96b080316e374017cc1bbdeb0c1adeec7503fdf36a8a0562d0912933%} TO ToSearchDateTime(CurrentDateTime.AddDays(900).ToShortDateString())]))
Now I know I problably didn't need to use the "rewritten" code Luke provided but I figured it didn't hurt, especially since it worked! Even more impressive are the additional functionality you have in Luke to search and modify your queries with live testing.
Final Thoughts
Having worked with Kentico for so long, you would have thought I'd have already dug into using the Luke tool to research some of these issues. I've heard others talk about it but just never had a need, until now. Guess the old saying is incorrect, you CAN teach an old dog new tricks!

Good Luck and Happy Coding!