Exemple #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <param name="umbracoHelper"></param>
        /// <param name="indexerName"></param>
        private void Indexer_DocumentWriting(object sender, DocumentWritingEventArgs e, UmbracoHelper umbracoHelper, string indexerName)
        {
            IPublishedContent publishedContent = null;

            publishedContent = umbracoHelper.TypedContent(e.NodeId);

            if (publishedContent == null)
            {
                // attempt to get as media
                publishedContent = umbracoHelper.TypedMedia(e.NodeId);

                if (publishedContent == null)
                {
                    // attempt to get as member
                    publishedContent = umbracoHelper.SafeTypedMember(e.NodeId);
                }
            }

            if (publishedContent != null)
            {
                this.EnsureUmbracoContext();

                var indexingContext = new IndexingContext(null, publishedContent, indexerName);

                LookService.Index(indexingContext, e.Document);
            }
        }
Exemple #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <param name="indexerName">Name of the indexer for which this DocumentWriting event is being executed on</param>
        private static void DocumentWriting(object sender, DocumentWritingEventArgs e, string indexerName)
        {
            IPublishedContent publishedContent = null;

            var indexerConfiguration = LookService.GetIndexerConfiguration(indexerName);

            if (indexerConfiguration.ShouldIndexContent) // attempt to get content
            {
                publishedContent = LookService.Instance._umbracoHelper.TypedContent(e.NodeId);
            }

            if (publishedContent == null && indexerConfiguration.ShouldIndexMedia) // attempt to get as media
            {
                publishedContent = LookService.Instance._umbracoHelper.TypedMedia(e.NodeId);
            }

            if (publishedContent == null && indexerConfiguration.ShouldIndexMembers) // attempt to get as member
            {
                publishedContent = LookService.Instance._umbracoHelper.SafeTypedMember(e.NodeId);
            }

            if (publishedContent != null)
            {
                var indexingContext = new IndexingContext(null, publishedContent, indexerName);

                LookService.EnsureContext();

                LookService.Index(indexingContext, e.Document);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <param name="indexerName">Name of the indexer for which this DocumentWriting event is being executed on</param>
        private static void DocumentWriting(object sender, DocumentWritingEventArgs e, string indexerName)
        {
            IPublishedContent publishedContent = null;

            if (LookService.Instance._umbracoHelper == null)
            {
                throw new Exception("Unexpected null value for UmbracoHelper - Look not initialized");
            }

            publishedContent = LookService.Instance._umbracoHelper.TypedContent(e.NodeId);

            if (publishedContent == null)
            {
                // attempt to get as media
                publishedContent = LookService.Instance._umbracoHelper.TypedMedia(e.NodeId);

                if (publishedContent == null)
                {
                    // attempt to get as member
                    publishedContent = LookService.Instance._umbracoHelper.SafeTypedMember(e.NodeId);
                }
            }

            if (publishedContent != null)
            {
                var indexingContext = new IndexingContext(
                    hostNode: null,
                    node: publishedContent,
                    indexerName: indexerName);

                LookService.EnsureContext();

                LookService.Index(indexingContext, e.Document);
            }
        }
        private static void IndexDate(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            DateTime?date = null;

            var dateIndexer = LookService.GetDateIndexer(indexingContext.IndexerName);

            if (dateIndexer != null)
            {
                try
                {
                    date = dateIndexer(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in date indexer", exception);
                }
            }
            else if (indexingContext.Item != null)
            {
                date = indexingContext.HostItem?.UpdateDate ?? indexingContext.Item.UpdateDate;
            }

            if (date != null)
            {
                var hasDateField = new Field(
                    LookConstants.HasDateField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var dateValue = DateTools.DateToString(date.Value, DateTools.Resolution.SECOND);

                var dateField = new Field(
                    LookConstants.DateField,
                    dateValue,
                    Field.Store.YES,
                    Field.Index.ANALYZED,
                    Field.TermVector.YES);

                var dateSortedField = new Field(
                    LuceneIndexer.SortedFieldNamePrefix + LookConstants.DateField,
                    dateValue,
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasDateField);
                document.Add(dateField);
                document.Add(dateSortedField);
            }
        }
        private List <LookTag> PropertiesToLookTags(List <string> properties, IndexingContext indexingContext)
        {
            var tags = new List <LookTag>();

            foreach (var key in properties)
            {
                var value = indexingContext.Item.GetPropertyValue <string>(key);
                if (!string.IsNullOrWhiteSpace(value))
                {
                    tags.Add(new LookTag(key + ":" + value));
                }
            }

            return(tags);
        }
        /// <summary>
        /// Index the supplied things
        /// </summary>
        /// <param name="things">The things to add into the index</param>
        /// <param name="beforeIndexing">optional action to call before indexing each thing</param>
        /// <param name="afterIndexing">optional acton to call after indexing each thing</param>
        internal static void IndexThings(IEnumerable <Thing> things, Action <IndexingContext> beforeIndexing = null, Action <IndexingContext> afterIndexing = null)
        {
            var nameStack     = new Stack <string>(things.Select(x => x.Name));
            var dateStack     = new Stack <DateTime?>(things.Select(x => x.Date));
            var textStack     = new Stack <string>(things.Select(x => x.Text));
            var tagStack      = new Stack <LookTag[]>(things.Select(x => x.Tags));
            var locationStack = new Stack <Location>(things.Select(x => x.Location));

            // use supplied, or do nothing
            LookConfiguration.BeforeIndexing = beforeIndexing;
            LookConfiguration.AfterIndexing  = afterIndexing;

            // setup indexers
            LookConfiguration.DefaultNameIndexer     = x => nameStack.Pop();
            LookConfiguration.DefaultDateIndexer     = x => dateStack.Pop();
            LookConfiguration.DefaultTextIndexer     = x => textStack.Pop();
            LookConfiguration.DefaultTagIndexer      = x => tagStack.Pop();
            LookConfiguration.DefaultLocationIndexer = x => locationStack.Pop();

            List <Document> documents = new List <Document>();

            foreach (var thing in things)
            {
                var document = new Document();

                var indexingContext = new IndexingContext(null, null, "UnitTestIndexer"); // null for IPublishedContent as not required

                LookService.Index(indexingContext, document);

                if (!indexingContext.Cancelled)
                {
                    documents.Add(document);
                }
            }

            //reset
            LookConfiguration.BeforeIndexing = null;
            LookConfiguration.AfterIndexing  = null;

            LookConfiguration.DefaultNameIndexer     = null;
            LookConfiguration.DefaultDateIndexer     = null;
            LookConfiguration.DefaultTextIndexer     = null;
            LookConfiguration.DefaultTagIndexer      = null;
            LookConfiguration.DefaultLocationIndexer = null;

            TestHelper.IndexDocuments(documents);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <param name="indexerName">Name of the indexer for which this DocumentWriting event is being executed on</param>
        private static void DocumentWriting(object sender, DocumentWritingEventArgs e, string indexerName)
        {
            IPublishedContent publishedContent = null;

            if (LookService.Instance._umbracoHelper == null)
            {
                throw new Exception("Unexpected null value for UmbracoHelper - Look not initialized");
            }

            publishedContent = LookService.Instance._umbracoHelper.TypedContent(e.NodeId);

            if (publishedContent == null)
            {
                // attempt to get as media
                publishedContent = LookService.Instance._umbracoHelper.TypedMedia(e.NodeId);

                if (publishedContent == null)
                {
                    // attempt to get as member
                    publishedContent = LookService.Instance._umbracoHelper.SafeTypedMember(e.NodeId);
                }
            }

            if (publishedContent != null)
            {
                var dummyHttpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("", "", new StringWriter())));

                UmbracoContext.EnsureContext(
                    dummyHttpContext,
                    ApplicationContext.Current,
                    new WebSecurity(dummyHttpContext, ApplicationContext.Current),
                    UmbracoConfig.For.UmbracoSettings(),
                    UrlProviderResolver.Current.Providers,
                    true,
                    false);

                var indexingContext = new IndexingContext(
                    hostNode: null,
                    node: publishedContent,
                    indexerName: indexerName);

                LookService.Index(indexingContext, e.Document);
            }
        }
Exemple #8
0
        private static void IndexText(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            var textIndexer = LookService.GetTextIndexer(indexingContext.IndexerName);

            if (textIndexer != null)
            {
                string text = null;

                try
                {
                    text = textIndexer(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in text indexer", exception);
                }

                if (text != null)
                {
                    var hasTextField = new Field(
                        LookConstants.HasTextField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    var textField = new Field(
                        LookConstants.TextField,
                        text,
                        Field.Store.YES,
                        Field.Index.ANALYZED,
                        Field.TermVector.YES);

                    document.Add(hasTextField);
                    document.Add(textField);
                }
            }
        }
Exemple #9
0
        //internal static void GenerateTestData()
        //{
        //    // generate a load of random test data, just to bulk it out
        //}

        /// <summary>
        /// Add supplied collection into the test index
        /// </summary>
        /// <param name="things"></param>
        internal static void IndexThings(IEnumerable <Thing> things)
        {
            var nameStack     = new Stack <string>(things.Select(x => x.Name));
            var dateStack     = new Stack <DateTime?>(things.Select(x => x.Date));
            var textStack     = new Stack <string>(things.Select(x => x.Text));
            var tagStack      = new Stack <LookTag[]>(things.Select(x => x.Tags));
            var locationStack = new Stack <Location>(things.Select(x => x.Location));

            // setup indexers
            LookConfiguration.NameIndexer     = x => nameStack.Pop();
            LookConfiguration.DateIndexer     = x => dateStack.Pop();
            LookConfiguration.TextIndexer     = x => textStack.Pop();
            LookConfiguration.TagIndexer      = x => tagStack.Pop();
            LookConfiguration.LocationIndexer = x => locationStack.Pop();

            // null for IPublishedContent as not required
            var indexingContext = new IndexingContext(null, null, null);

            List <Document> documents = new List <Document>();

            foreach (var thing in things)
            {
                var document = new Document();

                LookService.Index(indexingContext, document);

                documents.Add(document);
            }

            // reset indexers
            LookConfiguration.NameIndexer     = null;
            LookConfiguration.DateIndexer     = null;
            LookConfiguration.TextIndexer     = null;
            LookConfiguration.TagIndexer      = null;
            LookConfiguration.LocationIndexer = null;

            TestHelper.IndexDocuments(documents);
        }
        private static void IndexName(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            string name = null;

            var nameIndexer = LookService.GetNameIndexer(indexingContext.IndexerName);

            if (nameIndexer != null)
            {
                try
                {
                    name = nameIndexer(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in name indexer", exception);
                }
            }
            else if (indexingContext.Item != null)
            {
                name = indexingContext.Item.Name;
            }

            if (name != null)
            {
                var hasNameField = new Field(
                    LookConstants.HasNameField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var nameField = new Field(
                    LookConstants.NameField,
                    name,
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.YES);

                // field for lower case searching
                var nameFieldLowered = new Field(
                    LookConstants.NameField + "_Lowered",
                    name.ToLower(),
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.YES);

                var nameSortedField = new Field(
                    LuceneIndexer.SortedFieldNamePrefix + LookConstants.NameField,
                    name.ToLower(),                         // force case insentive sorting
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasNameField);
                document.Add(nameField);
                document.Add(nameFieldLowered);
                document.Add(nameSortedField);
            }
        }
Exemple #11
0
        private static void IndexTags(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            var tagIndexer = LookService.GetTagIndexer(indexingContext.IndexerName);

            if (tagIndexer != null)
            {
                LookTag[] tags = null;

                try
                {
                    tags = tagIndexer(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in tag indexer", exception);
                }

                if (tags != null)
                {
                    foreach (var tag in tags)
                    {
                        var hasTagsField = new Field(
                            LookConstants.HasTagsField,
                            "1",
                            Field.Store.NO,
                            Field.Index.NOT_ANALYZED);

                        // add all tags to a common field (serialized such that Tag objects can be restored from this)
                        var allTagsField = new Field(
                            LookConstants.AllTagsField,
                            tag.ToString(),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED);

                        // add the tag value to a specific field - this is used for searching on
                        var tagField = new Field(
                            LookConstants.TagsField + tag.Group,
                            tag.Name,
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED);

                        document.Add(hasTagsField);
                        document.Add(allTagsField);
                        document.Add(tagField);
                    }

                    var tagGroups = tags.Select(x => x.Group).Distinct();

                    foreach (var tagGroup in tagGroups)
                    {
                        var tagGroupField = new Field(
                            LookConstants.TagGroupField + tagGroup,
                            "1",
                            Field.Store.NO,
                            Field.Index.NOT_ANALYZED);

                        document.Add(tagGroupField);
                    }
                }
            }
        }
        private static void IndexLocation(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            var locationIndexer = LookService.GetLocationIndexer(indexingContext.IndexerName);

            if (locationIndexer != null)
            {
                Location location = null;

                try
                {
                    location = locationIndexer(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in location indexer", exception);
                }

                if (location != null)
                {
                    var hasLocationField = new Field(
                        LookConstants.HasLocationField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    var locationField = new Field(
                        LookConstants.LocationField,
                        location.ToString(),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    var locationLatitudeField = new Field(
                        LookConstants.LocationField + "_Latitude",
                        NumericUtils.DoubleToPrefixCoded(location.Latitude),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    var locationLongitudeField = new Field(
                        LookConstants.LocationField + "_Longitude",
                        NumericUtils.DoubleToPrefixCoded(location.Longitude),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    document.Add(hasLocationField);
                    document.Add(locationField);
                    document.Add(locationLatitudeField);
                    document.Add(locationLongitudeField);

                    foreach (var cartesianTierPlotter in LookService.Instance._cartesianTierPlotters)
                    {
                        var boxId = cartesianTierPlotter.GetTierBoxId(location.Latitude, location.Longitude);

                        var tierField = new Field(
                            cartesianTierPlotter.GetTierFieldName(),
                            NumericUtils.DoubleToPrefixCoded(boxId),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED_NO_NORMS);

                        document.Add(tierField);
                    }
                }
            }
        }
        /// <summary>
        ///  Do the indexing and set the field values onto the Lucene document
        /// </summary>
        /// <param name="indexingContext"></param>
        /// <param name="document"></param>
        internal static void Index(IndexingContext indexingContext, Document document)
        {
            var indexerConfiguration = LookService.GetIndexerConfiguration(indexingContext.IndexerName);

            if (!indexerConfiguration.ShouldIndexAlias(indexingContext.Item?.DocumentTypeAlias))
            {
                indexingContext.Cancel();
                return;
            }

            var stopwatch = Stopwatch.StartNew();

            try
            {
                LookService.GetBeforeIndexing()(indexingContext);
            }
            catch (Exception exception)
            {
                LogHelper.WarnWithException(typeof(LookService), "Error in global BeforeIndexing", exception);
            }

            try
            {
                LookService.GetBeforeIndexing(indexingContext.IndexerName)(indexingContext);
            }
            catch (Exception exception)
            {
                LogHelper.WarnWithException(typeof(LookService), "Error in indexer BeforeIndexing", exception);
            }

            LookService.IndexNode(indexingContext, document);

            LookService.IndexName(indexingContext, document);

            LookService.IndexDate(indexingContext, document);

            LookService.IndexText(indexingContext, document);

            LookService.IndexTags(indexingContext, document);

            LookService.IndexLocation(indexingContext, document);

            try
            {
                LookService.GetAfterIndexing(indexingContext.IndexerName)(indexingContext);
            }
            catch (Exception exception)
            {
                LogHelper.WarnWithException(typeof(LookService), "Error in indexer AfterIndexing", exception);
            }

            try
            {
                LookService.GetAfterIndexing()(indexingContext);
            }
            catch (Exception exception)
            {
                LogHelper.WarnWithException(typeof(LookService), "Error in global AfterIndexing", exception);
            }

            stopwatch.Stop();

            if (!indexingContext.Cancelled)
            {
                LogHelper.Debug(typeof(LookService), () => $"Building Lucene Document for Id='{indexingContext.Item.Id}', Key='{indexingContext.Item.GetGuidKey()}', Name='{indexingContext.Item.Name}' in Index '{ indexingContext.IndexerName }' Took { stopwatch.ElapsedMilliseconds }ms");
            }
        }
        /// <summary>
        ///  Do the indexing and set the field values onto the Lucene document
        /// </summary>
        /// <param name="indexingContext"></param>
        /// <param name="document"></param>
        internal static void Index(IndexingContext indexingContext, Document document)
        {
#if DEBUG
            var stopwatch = Stopwatch.StartNew();
#endif
            #region Node

            if (indexingContext.Item != null)
            {
                var publishedItemType = indexingContext?.HostItem?.ItemType ?? indexingContext.Item.ItemType;

                var hasNodeField = new Field(
                    LookConstants.HasNodeField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var nodeIdField = new Field(
                    LookConstants.NodeIdField,
                    indexingContext.Item.Id.ToString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED);

                var nodeKeyField = new Field(
                    LookConstants.NodeKeyField,
                    indexingContext.Item.GetGuidKey().GuidToLuceneString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED);

                var nodeTypeField = new Field(
                    LookConstants.NodeTypeField,
                    publishedItemType.ToString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                var nodeAliasField = new Field(
                    LookConstants.NodeAliasField,
                    indexingContext.Item.DocumentTypeAlias,
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasNodeField);
                document.Add(nodeIdField);
                document.Add(nodeKeyField);
                document.Add(nodeTypeField);
                document.Add(nodeAliasField);

                if (publishedItemType == PublishedItemType.Content)
                {
                    var culture = indexingContext?.HostItem?.GetCulture() ?? indexingContext.Item.GetCulture();

                    if (culture != null)
                    {
                        var cultureField = new Field(
                            LookConstants.CultureField,
                            culture.LCID.ToString(),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED,
                            Field.TermVector.NO);

                        document.Add(cultureField);
                    }
                }

                if (indexingContext.HostItem != null)
                {
                    var isDetachedField = new Field(
                        LookConstants.IsDetachedField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    // indexing detached item, so store the host context id so we can return the detached item
                    var hostIdField = new Field(
                        LookConstants.HostIdField,
                        indexingContext.HostItem.Id.ToString(),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    document.Add(isDetachedField);
                    document.Add(hostIdField);
                }
            }

            #endregion

            #region Name

            string name = null;

            if (LookService.GetNameIndexer() != null)
            {
                try
                {
                    name = LookService.GetNameIndexer()(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in name indexer", exception);
                }
            }
            else if (indexingContext.Item != null)
            {
                name = indexingContext.Item.Name;
            }

            if (name != null)
            {
                var hasNameField = new Field(
                    LookConstants.HasNameField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var nameField = new Field(
                    LookConstants.NameField,
                    name,
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.YES);

                // field for lower case searching
                var nameFieldLowered = new Field(
                    LookConstants.NameField + "_Lowered",
                    name.ToLower(),
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.YES);

                var nameSortedField = new Field(
                    LuceneIndexer.SortedFieldNamePrefix + LookConstants.NameField,
                    name.ToLower(),                         // force case insentive sorting
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasNameField);
                document.Add(nameField);
                document.Add(nameFieldLowered);
                document.Add(nameSortedField);
            }

            #endregion

            #region Date

            DateTime?date = null;

            if (LookService.GetDateIndexer() != null)
            {
                try
                {
                    date = LookService.GetDateIndexer()(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in date indexer", exception);
                }
            }
            else if (indexingContext.Item != null)
            {
                date = indexingContext.HostItem?.UpdateDate ?? indexingContext.Item.UpdateDate;
            }

            if (date != null)
            {
                var hasDateField = new Field(
                    LookConstants.HasDateField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var dateValue = DateTools.DateToString(date.Value, DateTools.Resolution.SECOND);

                var dateField = new Field(
                    LookConstants.DateField,
                    dateValue,
                    Field.Store.YES,
                    Field.Index.ANALYZED,
                    Field.TermVector.YES);

                var dateSortedField = new Field(
                    LuceneIndexer.SortedFieldNamePrefix + LookConstants.DateField,
                    dateValue,
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasDateField);
                document.Add(dateField);
                document.Add(dateSortedField);
            }

            #endregion

            #region Text

            if (LookService.GetTextIndexer() != null)
            {
                string text = null;

                try
                {
                    text = LookService.GetTextIndexer()(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in text indexer", exception);
                }

                if (text != null)
                {
                    var hasTextField = new Field(
                        LookConstants.HasTextField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    var textField = new Field(
                        LookConstants.TextField,
                        text,
                        Field.Store.YES,
                        Field.Index.ANALYZED,
                        Field.TermVector.YES);

                    document.Add(hasTextField);
                    document.Add(textField);
                }
            }

            #endregion

            #region Tag

            if (LookService.GetTagIndexer() != null)
            {
                LookTag[] tags = null;

                try
                {
                    tags = LookService.GetTagIndexer()(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in tag indexer", exception);
                }

                if (tags != null)
                {
                    foreach (var tag in tags)
                    {
                        var hasTagsField = new Field(
                            LookConstants.HasTagsField,
                            "1",
                            Field.Store.NO,
                            Field.Index.NOT_ANALYZED);

                        // add all tags to a common field (serialized such that Tag objects can be restored from this)
                        var allTagsField = new Field(
                            LookConstants.AllTagsField,
                            tag.ToString(),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED);

                        // add the tag value to a specific field - this is used for searching on
                        var tagField = new Field(
                            LookConstants.TagsField + tag.Group,
                            tag.Name,
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED);

                        document.Add(hasTagsField);
                        document.Add(allTagsField);
                        document.Add(tagField);
                    }
                }
            }

            #endregion

            #region Location

            if (LookService.GetLocationIndexer() != null)
            {
                Location location = null;

                try
                {
                    location = LookService.GetLocationIndexer()(indexingContext);
                }
                catch (Exception exception)
                {
                    LogHelper.WarnWithException(typeof(LookService), "Error in location indexer", exception);
                }

                if (location != null)
                {
                    var hasLocationField = new Field(
                        LookConstants.HasLocationField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    var locationField = new Field(
                        LookConstants.LocationField,
                        location.ToString(),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    var locationLatitudeField = new Field(
                        LookConstants.LocationField + "_Latitude",
                        NumericUtils.DoubleToPrefixCoded(location.Latitude),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    var locationLongitudeField = new Field(
                        LookConstants.LocationField + "_Longitude",
                        NumericUtils.DoubleToPrefixCoded(location.Longitude),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    document.Add(hasLocationField);
                    document.Add(locationField);
                    document.Add(locationLatitudeField);
                    document.Add(locationLongitudeField);

                    foreach (var cartesianTierPlotter in LookService.Instance._cartesianTierPlotters)
                    {
                        var boxId = cartesianTierPlotter.GetTierBoxId(location.Latitude, location.Longitude);

                        var tierField = new Field(
                            cartesianTierPlotter.GetTierFieldName(),
                            NumericUtils.DoubleToPrefixCoded(boxId),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED_NO_NORMS);

                        document.Add(tierField);
                    }
                }
            }

            #endregion
#if DEBUG
            stopwatch.Stop();
            LogHelper.Debug(typeof(LookService), $"Building Lucene Document For '{ indexingContext.Item.GetGuidKey() }' Took { stopwatch.ElapsedMilliseconds }ms");
#endif
        }
        private static void IndexNode(IndexingContext indexingContext, Document document)
        {
            if (indexingContext.Cancelled)
            {
                return;
            }

            if (indexingContext.Item != null)
            {
                var publishedItemType = indexingContext?.HostItem?.ItemType ?? indexingContext.Item.ItemType;

                var hasNodeField = new Field(
                    LookConstants.HasNodeField,
                    "1",
                    Field.Store.NO,
                    Field.Index.NOT_ANALYZED);

                var nodeIdField = new Field(
                    LookConstants.NodeIdField,
                    indexingContext.Item.Id.ToString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED);

                var nodeKeyField = new Field(
                    LookConstants.NodeKeyField,
                    indexingContext.Item.GetGuidKey().GuidToLuceneString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED);

                var nodeTypeField = new Field(
                    LookConstants.NodeTypeField,
                    publishedItemType.ToString(),
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                var nodeAliasField = new Field(
                    LookConstants.NodeAliasField,
                    indexingContext.Item.DocumentTypeAlias,
                    Field.Store.YES,
                    Field.Index.NOT_ANALYZED,
                    Field.TermVector.NO);

                document.Add(hasNodeField);
                document.Add(nodeIdField);
                document.Add(nodeKeyField);
                document.Add(nodeTypeField);
                document.Add(nodeAliasField);

                if (publishedItemType == PublishedItemType.Content)
                {
                    var culture = indexingContext?.HostItem?.GetCulture() ?? indexingContext.Item.GetCulture();

                    if (culture != null)
                    {
                        var cultureField = new Field(
                            LookConstants.CultureField,
                            culture.LCID.ToString(),
                            Field.Store.YES,
                            Field.Index.NOT_ANALYZED,
                            Field.TermVector.NO);

                        document.Add(cultureField);
                    }
                }

                if (indexingContext.HostItem != null)
                {
                    var isDetachedField = new Field(
                        LookConstants.IsDetachedField,
                        "1",
                        Field.Store.NO,
                        Field.Index.NOT_ANALYZED);

                    // indexing detached item, so store the host context id so we can return the detached item
                    var hostIdField = new Field(
                        LookConstants.HostIdField,
                        indexingContext.HostItem.Id.ToString(),
                        Field.Store.YES,
                        Field.Index.NOT_ANALYZED);

                    document.Add(isDetachedField);
                    document.Add(hostIdField);
                }
            }
        }