Kyle
Kyle

Reputation: 4366

Searching empty date fields in index

Somewhere between Sitecore 7.2 and 8.0 the logic for how empty date fields (i.e. date fields for which the content editor has not selected a value) are stored changed. They used to be be stored as DateTime.MinValue (i.e. 00010101); however, now they are stored as an empty string. Under Sitecore 7.2 I used to be able to run the following line of code to find all items that have no value selected for a given date field:

var myQuery = _searchContext.GetQueryable<MyClass>.Where(item => item.MyDateField == DateTime.MinValue);

Which generated the follow Lucene query: +mydatefield: 00010101

This of course no longer works since the field value in the index is an empty string. I'm not quite sure how to use the ContentSearch API to setup the query since DateTime can't be compared to a null or empty string value. I'm wondering if there's a way to query this new format or if I need to look into modifying how Sitecore stores empty date values to match the old format.

Upvotes: 1

Views: 1795

Answers (2)

Jay S
Jay S

Reputation: 7994

I believe you can use a nullable DateTime (DateTime?) for your field which should then have no value when the data is blank.

Your check can then be as simple as checking the HasValue property.

var myQuery = _searchContext.GetQueryable<MyClass>.Where(item => item.MyDateField.HasValue);

Upvotes: 0

Derek Hunziker
Derek Hunziker

Reputation: 13141

One approach you can take is to define a new boolean computed field that keeps track of the presence of the date field. This will make your queries easier to read, and it does not require special knowledge of how Sitecore matches empty fields. It is also likely to be future proof if a change is made to how the values are stored.

using System;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.ComputedFields;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;

namespace YourProject.ComputedFields
{
    public class HasDateComputedIndexField : IComputedIndexField
    {
        public object ComputeFieldValue(IIndexable indexable)
        {
            Item item = indexable as SitecoreIndexableItem;
            const string dateFieldName = "MyDateField";

            return 
                item != null &&
                item.Fields[dateFieldName] != null &&
                !((DateField)item.Fields[dateFieldName]).DateTime.Equals(DateTime.MinValue) &&
                !((DateField)item.Fields[dateFieldName]).DateTime.Equals(DateTime.MaxValue);
        }

        public string FieldName { get; set; }

        public string ReturnType { get; set; }
    }
}

The computed field will need to be added to your search configuration and your indexes rebuilt. From there, you can reference the computed field in your search result item class and query as follows:

public class MyClass : PageSearchResultItem
{
    [IndexField("has_date")]
    public bool HasDate { get; set; }
}

var myQuery = _searchContext.GetQueryable<MyClass>.Where(item => item.HasDate);

Upvotes: 3

Related Questions