public static void BuildIndex(FullTextIndexRebuildProc graph, RecordType item) { Debug.Print("Start processing {0}", item.Name); Stopwatch sw = new Stopwatch(); graph.Caches.Clear(); graph.Clear(PXClearOption.ClearAll); PXProcessing <RecordType> .SetCurrentItem(item); Type entity = GraphHelper.GetType(item.Entity); PXSearchableAttribute searchableAttribute = null; var list = graph.Caches[entity].GetAttributes("NoteID"); foreach (PXEventSubscriberAttribute att in list) { PXSearchableAttribute attribute = att as PXSearchableAttribute; if (attribute != null) { searchableAttribute = attribute; break; } } if (searchableAttribute == null) { return; } Type viewType; Type joinNote = typeof(LeftJoin <Note, On <Note.noteID, Equal <SearchIndex.noteID> > >); if (searchableAttribute.SelectForFastIndexing != null) { Type noteentity = entity; if (searchableAttribute.SelectForFastIndexing.IsGenericType) { Type[] tables = searchableAttribute.SelectForFastIndexing.GetGenericArguments(); if (tables != null && tables.Length > 0 && typeof(IBqlTable).IsAssignableFrom(tables[0])) { noteentity = tables[0]; } } Type joinSearchIndex = BqlCommand.Compose( typeof(LeftJoin <,>), typeof(SearchIndex), typeof(On <,>), typeof(SearchIndex.noteID), typeof(Equal <>), noteentity.GetNestedType("noteID")); viewType = BqlCommand.AppendJoin(searchableAttribute.SelectForFastIndexing, joinSearchIndex); viewType = BqlCommand.AppendJoin(viewType, joinNote); } else { Type joinSearchIndex = BqlCommand.Compose( typeof(LeftJoin <,>), typeof(SearchIndex), typeof(On <,>), typeof(SearchIndex.noteID), typeof(Equal <>), entity.GetNestedType("noteID")); viewType = BqlCommand.Compose(typeof(Select <>), entity); viewType = BqlCommand.AppendJoin(viewType, joinSearchIndex); viewType = BqlCommand.AppendJoin(viewType, joinNote); } BqlCommand cmd = BqlCommand.CreateInstance(viewType); PXView itemView = new PXView(graph, true, cmd); List <object> resultset; List <Type> fieldList = new List <Type>(searchableAttribute.GetSearchableFields(graph.Caches[entity])); Type entityForNoteId = entity; while (typeof(IBqlTable).IsAssignableFrom(entityForNoteId)) { Type tN = entityForNoteId.GetNestedType("noteID"); if (null != tN) { fieldList.Add(tN); } entityForNoteId = entityForNoteId.BaseType; } fieldList.Add(typeof(SearchIndex.noteID)); fieldList.Add(typeof(SearchIndex.category)); fieldList.Add(typeof(SearchIndex.content)); fieldList.Add(typeof(SearchIndex.entityType)); fieldList.Add(typeof(Note.noteID)); fieldList.Add(typeof(Note.noteText)); sw.Start(); int batchSize = 50000; int startRow = 0; do { using (new PXFieldScope(itemView, fieldList)) { //resultset = itemView.SelectMulti(); resultset = itemView.SelectWindowed(null, null, null, null, startRow, batchSize); } sw.Stop(); Debug.Print("{0} GetResultset in {1} sec. Total records={2}", item.DisplayName, sw.Elapsed.TotalSeconds, resultset.Count); sw.Reset(); sw.Start(); startRow += batchSize; int totalcount = resultset.Count; int cx = 0; int dx = 0; try { Dictionary <Guid, SearchIndex> insertDict = new Dictionary <Guid, SearchIndex>(resultset.Count); foreach (var res in resultset) { cx++; bool isSearchable = searchableAttribute.IsSearchable(graph.Caches[entity], ((PXResult)res)[entity]); if (isSearchable) { dx++; Note note = (Note)((PXResult)res)[typeof(Note)]; SearchIndex si = searchableAttribute.BuildSearchIndex(graph.Caches[entity], ((PXResult)res)[entity], (PXResult)res, ExtractNoteText(note)); SearchIndex searchIndex = (SearchIndex)((PXResult)res)[typeof(SearchIndex)]; if (searchIndex.NoteID != null && searchIndex.NoteID != si.NoteID) { PXSearchableAttribute.Delete(si); } if (searchIndex.NoteID == null) { if (!insertDict.ContainsKey(si.NoteID.Value)) { insertDict.Add(si.NoteID.Value, si); } } else if (si.Content != searchIndex.Content || si.Category != searchIndex.Category || si.EntityType != searchIndex.EntityType) { PXSearchableAttribute.Update(si); } } } sw.Stop(); Debug.Print("{0} Content building in {1} sec. Records processed = {2}. Searchable={3}", item.DisplayName, sw.Elapsed.TotalSeconds, totalcount, dx); sw.Reset(); sw.Start(); PXSearchableAttribute.BulkInsert(insertDict.Values); sw.Stop(); Debug.Print("{0} BulkInsert in {1} sec.", item.DisplayName, sw.Elapsed.TotalSeconds); } catch (Exception ex) { string msg = string.Format(Messages.OutOfProcessed, cx, totalcount, dx, ex.Message); throw new Exception(msg, ex); } } while (resultset.Count > 0); PXProcessing <RecordType> .SetProcessed(); }