internal void ExecuteCommit()
        {
            //need to send Examine all of the stuff to index for this unit of work

            //we need to 'stagger' the operations as it will be much faster to send all of the "Adds" to Examine at once and then each "Delete" one at a time.
            //because of the way Examine works, we also need to 'stagger' the index categories as well

            using (DisposableTimer.TraceDuration <ExamineTransaction>("Start adding indexes to Examine queue", "End adding indexes to Examine queue"))
            {
                var examineOperations = new List <IndexOperation>();

                //we track the TypedEntity revisions committed for 2 reasons (we're tracking the TypedEntity item in the revision):
                //  1: see below notes
                //  2: we need to update the status changed date if the status has in fact 'changed' since we need to reference in-memory objects as well
                var revisionsCommitted = new List <Tuple <TypedEntity, RevisionData> >();

                //this will get all of the lazy ids generated so we can use the values
                // to lookup some entities.
                var ids = _itemsToIndex.Where(x => x.OperationType == IndexOperationType.Add).Select(x => x.Id.Value)
                          .Concat(_itemsToIndex
                                  .Where(x => x.Fields.ContainsKey(FixedIndexedFields.EntityId) && x.OperationType == IndexOperationType.Add)
                                  .Select(x => x.Fields[FixedIndexedFields.EntityId].FieldValue.ToString()))
                          .Distinct()
                          .ToArray();

                while (_itemsToIndex.Any())
                {
                    var op = _itemsToIndex.Last();

                    examineOperations.Add(_frameworkContext.TypeMappers.Map <IndexOperation>(op));

                    //if its a typed entity revision:
                    // - track it so we can perform index cleanup on revisions
                    // - check status changed dates so we can ensure they are correct
                    if (op.IsRevision())
                    {
                        revisionsCommitted.Add(
                            EnsureCorrectStatusChangedDate(op, revisionsCommitted));
                    }

                    EnsureRelationEntities(op, ids);

                    //'dequeue' the item from the list
                    _itemsToIndex.RemoveAt(_itemsToIndex.Count - 1);
                }

                //now we have all of the indexing operations ready, lets do it
                ExamineManager.PerformIndexing(examineOperations.ToArray());

                //do some cleanup of the index data
                CleanupIndexedRevisions(revisionsCommitted);
            }
        }
        public override InstallStatus TryInstall()
        {
            _examineManager.PerformIndexing(new IndexOperation()
            {
                Item = new IndexItem()
                {
                    Id           = "ExamineInstalled".EncodeAsGuid().ToString("N"),
                    ItemCategory = "InstallRecord"
                },
                Operation = IndexOperationType.Add
            });

            return(new InstallStatus(InstallStatusType.Completed));
        }
        /// <summary>
        /// Need to do a bit of cleanup now for Revision entries to ensure that we keep the records flagged as IsLatest to a minimum.
        /// To do this we'll lookup all revisions in the index that are marked as IsLatest that have Ids of revisions that we've just committed
        /// that have a UtcModified date of less than the ones we've just committed... thankfully, Lucene has a Range query that we can
        /// use to do this cleanup
        /// </summary>
        /// <param name="revisionsCommitted">The revisions committed during this transaction</param>
        private void CleanupIndexedRevisions(IEnumerable <Tuple <TypedEntity, RevisionData> > revisionsCommitted)
        {
            foreach (var r in revisionsCommitted)
            {
                //TODO: Figure out how Lucene is dealing with DateTime and UTC... currently were putting it back a day
                // but if we can do an Hour that would be better, just need to figure out what it is storing.
                var criteria = ExamineManager.CreateSearchCriteria()
                               .Must().EntityType <TypedEntity>()
                               .Must().HiveId(r.Item1.Id, FixedIndexedFields.EntityId)
                               .Must().Field(FixedRevisionIndexFields.IsLatest, "1".Escape())
                               .Must().Range(FixedIndexedFields.UtcModified, DateTime.MinValue, r.Item1.UtcModified.UtcDateTime.AddDays(-1));

                foreach (var i in ExamineManager.Search(criteria.Compile()))
                {
                    //convert the fields returned
                    var fields = i.Fields.ToDictionary(f => f.Key, f => new ItemField(f.Value));

                    //remove the flag
                    fields[FixedRevisionIndexFields.IsLatest] = new ItemField(0)
                    {
                        DataType = FieldDataType.Int
                    };

                    //now we need to update the index item to not be latest
                    var updateOp = new IndexOperation
                    {
                        Operation = IndexOperationType.Add,
                        Item      = new IndexItem
                        {
                            Fields       = fields,
                            Id           = i.Id,
                            ItemCategory = i.Fields[LuceneIndexer.IndexCategoryFieldName]
                        }
                    };

                    //do the update
                    ExamineManager.PerformIndexing(updateOp);
                }
            }
        }