2

I have a class (SBJSearchItem) that inherits SearchResultItem that I'm using with the ContentSearchManager. The problem is that some of my SBJSearchItem properties are not populating. I'm using Azure Search as part of Sitecore Azure PaaS.

public class SBJSearchItem : SearchResultItem
{
    #region Public Properities

    // Type is working. This stores an ID and comes back as a string, which is fine.
    [IndexField("type")]
    public string Type { get; set; }

    // Authors is working. This stores a list of IDs.
    [IndexField("authors")]
    public string Authors { get; set; }

    // Title is working. It stores a string.
    [IndexField("title")]
    public string Title { get; set; }

    /*
    Publish Date does not work. This is just a date/time field in Sitecore.
    It is stored as a string type in the index. I made it nullable because
    I get an error that says that it cannot convert null to DataTime.
    I believe that's because it also pulls the template which doesn't have
    a date set.
    */
    [IndexField("publish_date")]
    public DateTime? PublishDate { get; set; }

    // Section does not work. It is a computed field that I set to a string.
    [IndexField("section")]
    public string Section { get; set; }

    /*
    DateSearch does not work. This is a computed field. It is stored as a 
    DateTimeOffset type. I get a DateTime.MinValue.
    */
    // EDIT: Added this per comments
    [TypeConverter(typeof(IndexFieldDateTimeValueConverter))]
    [IndexField("date_search")]
    public DateTime DateSearch { get; set; }

    #endregion
}

Edit 4 Apparently getting the index in the manner that I was doesn't work the same as getting the index specifically by name.

Here's an example of how I'm executing the query:

// Be careful if you use the commented lines here:
//var indexableItem = new SitecoreIndexableItem(currentStory);
//var index = ContentSearchManager.GetIndex(indexableItem);

// This apparently is DIFFERENT than the previous index declaration above
var index = ContentSearchManager.GetIndex("sitecore_master_index");

using (var context = index.CreateSearchContext())
{
    var query = context.GetQueryable<SBJSearchItem>()
                .Where(i => i.TemplateId == SitecoreItemIds.BLOG_STORY_TEMPLATE
                    && i.ItemId == currentStory.ID)
                .ToList();
}

The query works except those few properties that I mentioned above are null in my list of items (well one item in this case).

Here's my patch that adds the computed fields into the index. I have verified that the values are actually in the index.

      <index id="sitecore_master_index">
        <configuration>
          <!-- EDIT: Added per comments -->
          <fieldMap type="Sitecore.ContentSearch.Azure.FieldMaps.CloudFieldMap, Sitecore.ContentSearch.Azure">
            <fieldNames hint="raw:AddFieldByFieldName">
              <field type="System.String"   fieldName="section"     cloudFieldName="section"     boost="1f" settingType="Sitecore.ContentSearch.Azure.CloudSearchFieldConfiguration, Sitecore.ContentSearch.Azure"/>
              <field type="System.DateTime" fieldName="date_search" cloudFieldName="date_search" boost="1f" format="yyyy-MM-ddTHH:mm:ssZ" settingType="Sitecore.ContentSearch.Azure.CloudSearchFieldConfiguration, Sitecore.ContentSearch.Azure"/>
            </fieldNames>
          </fieldMap>
          <!-- END EDIT -->
          <fields hint="raw:AddComputedIndexField">
            <field fieldName="section" storageType="yes" indexType="tokenized">
              SBJSitecore.Components.Editorial.SectionComputedField,SBJSitecore
            </field>
            <field fieldName="date_search" storageType="yes" indexType="tokenized" type="System.DateTime">
              SBJSitecore.Components.Editorial.DateSearchComputedField,SBJSitecore
            </field>
          </fields>
        </configuration>
      </index>

EDIT 2

Per comments added my Computed fields into the Map. Reindex and tried again. Still not returning

<cloudTypeMapper type="Sitecore.ContentSearch.Azure.Schema.CloudSearchTypeMapper, Sitecore.ContentSearch.Azure" patch:source="Sitecore.ContentSearch.Azure.Index.SectionField.config">
    <maps hint="raw:AddMap" patch:source="Sitecore.ContentSearch.Azure.Index.SectionField.config">
        <map type="System.Char" cloudType="Edm.String"/>
        <map type="System.String" cloudType="Edm.String"/>
        <map type="System.Guid" cloudType="Edm.String"/>
        <map type="System.Int32" cloudType="Edm.Int32"/>
        <map type="System.Int64" cloudType="Edm.Int64"/>
        <map type="System.Double" cloudType="Edm.Double"/>
        <map type="System.Single" cloudType="Edm.Double"/>
        <map type="System.Boolean" cloudType="Edm.Boolean"/>
        <map type="System.DateTime" cloudType="Edm.DateTimeOffset"/>
        <map type="System.DateTimeOffset" cloudType="Edm.DateTimeOffset"/>
        <map type="System.String[]" cloudType="Collection(Edm.String)"/>
        <map type="System.Guid[]" cloudType="Collection(Edm.String)"/>
        <map type="System.Int32[]" cloudType="Collection(Edm.String)"/>
        <map type="System.Object[]" cloudType="Collection(Edm.String)"/>
        <map type="Sitecore.ContentSearch.IIndexableId, Sitecore.ContentSearch" cloudType="Edm.String"/>
        <map type="Sitecore.ContentSearch.IIndexableUniqueId, Sitecore.ContentSearch" cloudType="Edm.String"/>
        <map type="Sitecore.Data.ID, Sitecore.Kernel" cloudType="Edm.String"/>
        <map type="Sitecore.Data.ItemUri, Sitecore.Kernel" cloudType="Edm.String"/>
        <map type="Sitecore.ContentSearch.SitecoreItemId, Sitecore.ContentSearch" cloudType="Edm.String"/>
        <map type="Sitecore.ContentSearch.SitecoreItemUniqueId, Sitecore.ContentSearch" cloudType="Edm.String"/>
        <map type="Sitecore.Marketing.Taxonomy.Model.TaxonUri, Sitecore.Marketing.Taxonomy" cloudType="Edm.String"/>
        <map type="Sitecore.Marketing.Definitions.TaxonomicClassification, Sitecore.Marketing" cloudType="Edm.String"/>
        <!-- Patched these values in -->
        <map type="SBJSitecore.Components.Editorial.SectionComputedField,SBJSitecore" cloudType="Edm.String" patch:source="Sitecore.ContentSearch.Azure.Index.SectionField.config"/>
        <map type="SBJSitecore.Components.Editorial.DateSearchComputedField,SBJSitecore" cloudType="Edm.DateTimeOffset" patch:source="Sitecore.ContentSearch.Azure.Index.SectionField.config"/>
        <!-- End Patch -->
    </maps>
</cloudTypeMapper>

Snippit of the index:

"value": [
    {
        "date_search": "2017-02-14T17:23:00Z",
        "publish_date": "20170214T122300",
    }
]

EDIT

I made a couple of edits per comments. Neither of these changes seem to have any impact. I am in touch with Sitecore support on this issue.

I also noticed that the CreatedDate & Updated fields are DateTime.MinValue on my search results (var query above).

  • Im noticing that you are using "sitecore_master_index", Is your item in your search query also coming from master database? – Ahmed Okour Apr 19 '17 at 17:34
  • It is. I do intend on using a custom index at some point, but for now this is in master. – Kevin Apr 19 '17 at 17:37
  • I would start by looking at a functional DateTime property in the Sitecore.ContentSearch.SearchTypes.SearchResultItem Type (CreatedDate, Updated) and its related configuration (AddComputedIndexField, AddFieldByFieldName) with /sitecore/admin/showconfig.aspx. Make sure that the index you're using has the correct definition of the field in its schema. You can also try decorating the POCO property with a TypeConverter attribute since the value is in the index as a string: [TypeConverter(typeof(IndexFieldDateTimeValueConverter))] – Nathan Hase Apr 19 '17 at 21:05
  • Try adding your computed fields in the fieldmap as well. With storageType and indexType, but make sure to use the correct syntax - check the default config for Azure Search as this is different from the Lucene one (used in the answers below). – Gatogordo Apr 20 '17 at 11:49
  • @IsNull Good suggestions. I updated my question reflecting the changes, but alas no better. – Kevin Apr 20 '17 at 12:04
1

When getting the index it seems like it is better to call an index by name

I was calling the index like so:

var indexableItem = new SitecoreIndexableItem(currentStory);
var index = ContentSearchManager.GetIndex(indexableItem);

But it didn't work as expected.

So I changed it to this:

var index = ContentSearchManager.GetIndex("sitecore_master_index");

And it works properly.

  • I had the same issue and this was the fix – Anh-Duc Sep 10 at 14:08
0

Add a date mask in the configuration:

<field fieldName="pubdate" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.DateTime" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" format="yyyyMMdd" />

  • I looked at the other fields in ShowConfig and replicated them. This didn't help any. I also noticed that the system date/time fields are not working. Seems to be a Sitecore bug. – Kevin Apr 20 '17 at 12:02
0

Let me summary the outcome of this issue, in case somebody will face it in the future.

Field #1

[IndexField("publish_date")]` public DateTime PublishDate { get; set; }

In an index's schema, the publish_date field was defined as Edm.String date type, like shown below:

{ "@odata.context": "https://[search-service-name].search.windows.net/$metadata#indexes/$entity", "@odata.etag": "\"0x1B38DCC03076AB8\"", "name": "sitecore-master-index", "fields": [ ... { "name": "publish_date", "type": "Edm.String", ... }, ... ], ... }

A value was stored in the same format as Sitecore keeps it when viewing Raw Values:

{ "@odata.context": "...", "value": [ { ... "publish_date": "20161208T073400", ... } ] }

As a result, when Sitecore tried populating an instance of a POCO class, it caused the following exception:

System.FormatException: 'String was not recognized as a valid DateTime.'.

Solutions:

  1. In a POCO class, change type from the DateTime to string.

OR

  1. In an index schema, change type from the Edm.String to Edm.DateTimeOffset.

Field #2

[IndexField("section")] public string Section { get; set; }

If an index'a document has no value, then an instance of a POCO class will have no value either.

{ "@odata.context": "...", "value": [ { ... "section": null, ... } ] }

Solution

  1. Get a document from an index and check whether it has any value or not.

Field #3

[IndexField("date_search")] public DateTime DateSearch { get; set; }

When calling the ContentSearchManager.GetIndex(IIndexable indexable) method, Sitecore triggers the contentSearch.getContextIndex pipeline to resolve an index name.

<contentSearch.getContextIndex patch:source="Sitecore.ContentSearch.config"> <processor type="Sitecore.ContentSearch.Pipelines.GetContextIndex.FetchIndex, Sitecore.ContentSearch" />

While calling the ContentSearchManager.GetIndex(string name) one, you directly say which index you want to use.

Solution:

  1. When using the ContentSearchManager.GetIndex(new SitecoreIndexableItem(item)) method, check what you have in the above pipeline to make sure there is no custom processor that might change the default behavior.

NB: There is REST API for Azure Search, which you can use to get data from your index before map it on an instance of a POCO class.

Additionally, Postman is my favorite tool when I need to work with any REST API

Best Wishes, Oleg

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.