diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs index 0c01e2e6..60cc2998 100644 --- a/server/AyaNova/Controllers/AttachmentController.cs +++ b/server/AyaNova/Controllers/AttachmentController.cs @@ -237,7 +237,7 @@ namespace AyaNova.Api.Controllers //SEARCH INDEXING // Search.ProcessNewObjectKeywords( UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName, v.DisplayFileName, v.Notes, v.StoredFileName); var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleIdFromContext.Id(HttpContext.Items), v.Id, AyaType.FileAttachment, v.DisplayFileName); - SearchParams.AddWord(v.Notes).AddWord(v.DisplayFileName).AddWord(v.StoredFileName); + SearchParams.AddText(v.Notes).AddText(v.DisplayFileName).AddText(v.StoredFileName); Search.ProcessNewObjectKeywords(SearchParams); } diff --git a/server/AyaNova/biz/CustomFieldsValidator.cs b/server/AyaNova/biz/CustomFieldsValidator.cs index 700b6165..443b41b0 100644 --- a/server/AyaNova/biz/CustomFieldsValidator.cs +++ b/server/AyaNova/biz/CustomFieldsValidator.cs @@ -14,11 +14,8 @@ namespace AyaNova.Biz //No form custom = no template to check against so nothing to do if (formCustom == null) return; - - - //var OuterJson = JObject.Parse(formCustom.Template); - var FormTemplate = JArray.Parse(formCustom.Template); - //var FormTemplate = (JArray)OuterJson["template"]; + + var FormTemplate = JArray.Parse(formCustom.Template); var ThisFormCustomFieldsList = FormAvailableFields.FormFields(formCustom.FormKey).Where(x => x.Custom == true).Select(x => x.Key).ToList(); //If the customFields string is empty then only validation is if any of the fields are required to be filled in @@ -46,6 +43,8 @@ namespace AyaNova.Biz //NOTE: to save bandwidth the actual custom fields look like this: // - {c1:"blah",c2:"blah",c3:"blah".....c16:"blah"} //However the LT field names might be WidgetCustom1 or UserCustom16 so we need to translate by EndsWith + + //Top level object is a Object not an array when it comes to custom fields and the key names are the custom fields abbreviated var CustomFieldData = JObject.Parse(customFields); //make sure all the *required* keys are present diff --git a/server/AyaNova/biz/Search.cs b/server/AyaNova/biz/Search.cs index 1bf9ee61..bea0e1d3 100644 --- a/server/AyaNova/biz/Search.cs +++ b/server/AyaNova/biz/Search.cs @@ -394,7 +394,7 @@ namespace AyaNova.Biz } - public SearchIndexProcessObjectParameters AddWord(string s) + public SearchIndexProcessObjectParameters AddText(string s) { if (!string.IsNullOrWhiteSpace(s)) { @@ -402,12 +402,14 @@ namespace AyaNova.Biz } return this; } - public SearchIndexProcessObjectParameters AddWord(uint u) + + public SearchIndexProcessObjectParameters AddText(uint u) { Words.Add(u.ToString()); return this; } - public SearchIndexProcessObjectParameters AddWord(List lWords) + + public SearchIndexProcessObjectParameters AddText(List lWords) { if (lWords != null) { @@ -423,6 +425,15 @@ namespace AyaNova.Biz return this; } + + public SearchIndexProcessObjectParameters AddCustomFields(string jsonString) + { + //Extract the text from custom fields json fragment as an array of strings and add it here + AddText(JsonUtil.GetCustomFieldsAsStringArrayForSearchIndexing(jsonString)); + return this; + } + + } @@ -997,6 +1008,10 @@ namespace AyaNova.Biz #endregion + #region Utility + + #endregion utility + }//eoc }//eons \ No newline at end of file diff --git a/server/AyaNova/biz/UserBiz.cs b/server/AyaNova/biz/UserBiz.cs index cdb352f4..f816cc8f 100644 --- a/server/AyaNova/biz/UserBiz.cs +++ b/server/AyaNova/biz/UserBiz.cs @@ -60,7 +60,7 @@ namespace AyaNova.Biz inObj.Tags = TagUtil.NormalizeTags(inObj.Tags); - inObj.CustomFields=JsonUtil.CompactJson(inObj.CustomFields); + inObj.CustomFields = JsonUtil.CompactJson(inObj.CustomFields); //Seeder sets user options in advance so no need to create them here in that case if (inObj.UserOptions == null) @@ -82,10 +82,9 @@ namespace AyaNova.Biz //Log event EventLogProcessor.LogEventToDatabase(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), ct); - //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, inObj.Id, BizType, inObj.Name); - SearchParams.AddWord(inObj.Notes).AddWord(inObj.Name).AddWord(inObj.EmployeeNumber).AddWord(inObj.Tags); - Search.ProcessNewObjectKeywords(SearchParams); + //SEARCH INDEXING + SearchIndex(inObj, true); + //TAGS TagUtil.ProcessUpdateTagsInRepository(ct, inObj.Tags, null); @@ -103,8 +102,8 @@ namespace AyaNova.Biz inObj.Password = Hasher.hash(inObj.Salt, inObj.Password); inObj.Tags = TagUtil.NormalizeTags(inObj.Tags); - inObj.CustomFields=JsonUtil.CompactJson(inObj.CustomFields); - + inObj.CustomFields = JsonUtil.CompactJson(inObj.CustomFields); + //Seeder sets user options in advance so no need to create them here in that case if (inObj.UserOptions == null) inObj.UserOptions = new UserOptions(); @@ -126,9 +125,7 @@ namespace AyaNova.Biz EventLogProcessor.LogEventToDatabase(new Event(UserId, inObj.Id, BizType, AyaEvent.Created), TempContext); //SEARCH INDEXING - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, inObj.Id, BizType, inObj.Name); - SearchParams.AddWord(inObj.Notes).AddWord(inObj.Name).AddWord(inObj.EmployeeNumber).AddWord(inObj.Tags); - Search.ProcessNewObjectKeywords(SearchParams); + SearchIndex(inObj, true); //TAGS TagUtil.ProcessUpdateTagsInRepository(TempContext, inObj.Tags, null); @@ -260,8 +257,6 @@ namespace AyaNova.Biz //put internal bool Put(User dbObj, User inObj) { - - //Get a snapshot of the original db value object before changes User SnapshotOfOriginalDBObj = new User(); CopyObject.Copy(dbObj, SnapshotOfOriginalDBObj); @@ -296,10 +291,8 @@ namespace AyaNova.Biz //Log modification EventLogProcessor.LogEventToDatabase(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); - //Update keywords - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, dbObj.Id, BizType, dbObj.Name); - SearchParams.AddWord(dbObj.Notes).AddWord(dbObj.Name).AddWord(dbObj.EmployeeNumber).AddWord(dbObj.Tags); - Search.ProcessUpdatedObjectKeywords(SearchParams); + + SearchIndex(dbObj, false); TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); @@ -319,7 +312,7 @@ namespace AyaNova.Biz //Do the patching objectPatch.ApplyTo(dbObj); dbObj.Tags = TagUtil.NormalizeTags(dbObj.Tags); - dbObj.CustomFields=JsonUtil.CompactJson(dbObj.CustomFields); + dbObj.CustomFields = JsonUtil.CompactJson(dbObj.CustomFields); //Is the user patching the password? if (!string.IsNullOrWhiteSpace(dbObj.Password) && dbObj.Password != SnapshotOfOriginalDBObj.Password) @@ -335,12 +328,7 @@ namespace AyaNova.Biz //Log modification EventLogProcessor.LogEventToDatabase(new Event(UserId, dbObj.Id, BizType, AyaEvent.Modified), ct); - - //Update keywords - // Search.ProcessUpdatedObjectKeywords(UserLocaleId, dbObj.Id, BizType, dbObj.Name, dbObj.EmployeeNumber, dbObj.Notes, dbObj.Name); - var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, dbObj.Id, BizType, dbObj.Name); - SearchParams.AddWord(dbObj.Notes).AddWord(dbObj.Name).AddWord(dbObj.EmployeeNumber).AddWord(dbObj.Tags); - Search.ProcessUpdatedObjectKeywords(SearchParams); + SearchIndex(dbObj, false); TagUtil.ProcessUpdateTagsInRepository(ct, dbObj.Tags, SnapshotOfOriginalDBObj.Tags); @@ -348,6 +336,19 @@ namespace AyaNova.Biz } + private void SearchIndex(User obj, bool isNew) + { + //SEARCH INDEXING + var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, obj.Id, BizType, obj.Name); + SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.EmployeeNumber).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + + if (isNew) + Search.ProcessNewObjectKeywords(SearchParams); + else + Search.ProcessUpdatedObjectKeywords(SearchParams); + } + + //////////////////////////////////////////////////////////////////////////////////////////////// //DELETE // diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs index 6e1ca1da..a0eaedd7 100644 --- a/server/AyaNova/biz/WidgetBiz.cs +++ b/server/AyaNova/biz/WidgetBiz.cs @@ -231,7 +231,9 @@ namespace AyaNova.Biz { //SEARCH INDEXING var SearchParams = new Search.SearchIndexProcessObjectParameters(UserLocaleId, obj.Id, BizType, obj.Name); - SearchParams.AddWord(obj.Notes).AddWord(obj.Name).AddWord(obj.Serial).AddWord(obj.Tags); + SearchParams.AddText(obj.Notes).AddText(obj.Name).AddText(obj.Serial).AddText(obj.Tags).AddCustomFields(obj.CustomFields); + + if (isNew) Search.ProcessNewObjectKeywords(SearchParams); else diff --git a/server/AyaNova/util/JsonUtil.cs b/server/AyaNova/util/JsonUtil.cs index f2e05c0b..eec264ab 100644 --- a/server/AyaNova/util/JsonUtil.cs +++ b/server/AyaNova/util/JsonUtil.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -39,6 +40,37 @@ namespace AyaNova.Util } + /// + /// Utility used by biz classes to extract all the custom field data as text strings suitable for search indexing + /// Does not take into account type of field only what is in it and weeds out bools and any other non suitable for search text + /// + /// + /// + public static List GetCustomFieldsAsStringArrayForSearchIndexing(string jsonIn) + { + var ret = new List(); + + if (!string.IsNullOrWhiteSpace(jsonIn)) + { + var j = JObject.Parse(jsonIn); + + //iterate the values in the custom fields + foreach (KeyValuePair kv in j) + { + //Add as string any value that isn't a bool since bools are useless for searching + //and don't add dates as it gets hellish to factor in time zone conversions and local server vs user date format and all that shit + //and at the end of the day it won't really be useful for searching as people will probably ask for a filter or sort instead which we may have to + //look at in future, for search though just the numbers and text that are plausibly search-worthy + if (kv.Value.Type != JTokenType.Boolean && kv.Value.Type != JTokenType.Date) + { + ret.Add(kv.Value.Value()); + } + } + } + return ret; + } + + }//eoc }//eons \ No newline at end of file