public XSearchObjJSON(XSearchObj obj) { id = obj.id_service.ToString(); alias = obj.alias.ToString(); name = obj.scen_alias.ToString(); DisplayName = obj.name_service.ToString(); logo = obj.logo.ToString(); //message = obj.message.ToString(); }
//создаем "документ" в терминологии Lucene (как элемент поиска) Document CreateDocument(ref XSearchObj service) { Document doc = new Document(); doc.Add(new Field(Helper.GETNAME(new { service.id_service }), new string(service.id_service), Field.Store.YES, Field.Index.NOT_ANALYZED)); //(индексируется как id) doc.Add(new Field(Helper.GETNAME(new { service.alias }), new string(service.alias), Field.Store.YES, Field.Index.NOT_ANALYZED)); //(индексируется без анализа) doc.Add(new Field(Helper.GETNAME(new { service.scen_alias }), new string(service.scen_alias), Field.Store.YES, Field.Index.NOT_ANALYZED)); //(индексируется без анализа) doc.Add(new Field(Helper.GETNAME(new { service.name_service }), new string(service.name_service), Field.Store.YES, Field.Index.NO)); doc.Add(new Field(Helper.GETNAME(new { service.logo }), new string(service.logo), Field.Store.YES, Field.Index.NO)); //(не индексируется) doc.Add(new Field(Helper.GETNAME(new { service.version }), new string(service.version), Field.Store.YES, Field.Index.NO)); //(не индексируется) //*******!!!! Внимание индексируется без норм (если нужна морфология и провинутые яз. возможности, то включить)********** doc.Add(new Field(Helper.GETNAME(new { service.search_tag }), new string(service.search_tag), Field.Store.YES, Field.Index.ANALYZED_NO_NORMS)); //*******!!!! Внимание ниже добавлено дополнительное поле для поиска по ключевым словам********** //doc.Add(new Field(Helper.GETNAME(new { service.name_service }), new string(service.name_service), Field.Store.YES, Field.Index.ANALYZED_NO_NORMS)); return(doc); }
//для записи из БД по одной записи (обязательно делать WriterClose после всех записей!!!) public void AddDocument(XSearchObj service) { lock (searchLock) { try { GlobalWriter.AddDocument(CreateDocument(ref service)); } catch (Exception ex) { if (ex is OutOfMemoryException || ex is NullReferenceException) { //закрываем writer GlobalWriter.Dispose(); return; } throw new Exception("Error adding document! \n" + ex.Message); } } }
//вспомогательный метод для парсинга Xml private void fillXmlItem(bool menu, ref List <XSearchObj> scenAliasList, ref string scen_alias, ref string service_alias) { XSearchObj fromMenuitem = new XSearchObj(); if (scen_alias != null && service_alias == null) { fromMenuitem.scen_alias = scen_alias.ToCharArray(); //так как service_alias пуст, добавим в service_alias псевдоним сценария fromMenuitem.alias = scen_alias.ToCharArray(); //добавление в коллекцию LuceneIndex либо в коллекцию scenAliasList.Add(fromMenuitem); } else if (scen_alias != null && service_alias != null) { fromMenuitem.alias = (menu) ? service_alias.ToCharArray() : scen_alias.ToCharArray(); fromMenuitem.scen_alias = (menu) ? scen_alias.ToCharArray() : service_alias.ToCharArray(); //добавление в коллекцию LuceneIndex либо в коллекцию scenAliasList.Add(fromMenuitem); } }
//для "внутреннего использования" void AddDocument(ref IndexWriter writer, XSearchObj service) { lock (searchLock) { try { writer.AddDocument(CreateDocument(ref service)); //writer.UpdateDocument(new Term("id_service"), CreateDocument(ref service)); //writer.Dispose(); } catch (Exception ex) { if (ex is OutOfMemoryException || ex is NullReferenceException) { //закрываем writer writer.Dispose(); //Console.WriteLine("Error adding document! \n" + ex.Message); return; } throw new Exception("Error adding document! \n" + ex.Message); } } }
//ищем в индексе услуги по alias-у и дополняем в индексе поля с незаданным scen_alias (алиас сценария) public void MergeWithScenAliasList(IEnumerable <XSearchObj> list, bool withoutMenu) { lock (searchLock) { IndexWriter catalogWriter = Initialize(ref _catalogPath, false, false); //IndexReader reader = IndexReader.Open(catalogPath, false); //ReadOnly = false IndexReader reader = catalogWriter.GetReader(); IndexSearcher searcher = new IndexSearcher(reader); //поиск по alias-у foreach (XSearchObj obj in list) { //ищем есть ли в индексе услуга с соответвующим алиасом Term aliasTerm = new Term(Helper.GETNAME(new { obj.alias }), new string(obj.alias)); Query query = new TermQuery(aliasTerm); //TODO: посмотреть все ли результаты отдает, если нет, писать свой CustomCollector (важно!!!) TopDocs docs = searcher.Search(query, maxHitsPerSearch); ScoreDoc[] hits = docs.ScoreDocs; if (docs.TotalHits > 0) { //пробегаем по результатам и for (int i = 0; i < docs.TotalHits; i++) { ScoreDoc t = hits[i]; Document doc = searcher.Doc(t.Doc); //int docId = t.Doc; try { //***********удаляем старый документ (по запросу) !!!Если есть дубли может возникнуть ошибка в цикле, обработать!!!****** catalogWriter.DeleteDocuments(query); } catch (OutOfMemoryException) { catalogWriter.Dispose(); throw; } XSearchObj temp = new XSearchObj { id_service = doc.Get(Helper.GETNAME(new { obj.id_service })).ToCharArray(), alias = doc.Get(Helper.GETNAME(new { obj.alias })).ToCharArray(), scen_alias = obj.scen_alias, name_service = doc.Get(Helper.GETNAME(new { obj.name_service })).ToCharArray(), logo = doc.Get(Helper.GETNAME(new { obj.logo })).ToCharArray(), version = doc.Get(Helper.GETNAME(new { obj.version })).ToCharArray(), search_tag = doc.Get(Helper.GETNAME(new { obj.search_tag })).ToCharArray() }; //Term scenAlias = new Term("scen_alias", obj.scen_alias.ToString()); //catalogWriter.UpdateDocument(scenAlias, doc); //добавляем обновленный (с именем сценария) catalogWriter.AddDocument(CreateDocument(ref temp)); } } } if (!withoutMenu) { //удаляем все из индекса что не содержит алиаса сценария try { Term emptyScenAlias = new Term(Helper.GETNAME(new { read_xsobj_field.scen_alias }), String.Empty); catalogWriter.DeleteDocuments(emptyScenAlias); } catch (Exception ex) { catalogWriter.Dispose(); throw ex; } } Optimize(ref catalogWriter); Dispose(ref catalogWriter); } }
//*************парсим setting.xml для поиска имен сценариев ассоциированных услугам***************** //TODO: убрать лишние XSearchObj fromScenario = new XSearchObj(); использовать глобальный объект для добавления (который для чтения имени полей) public List <XSearchObj> ParseSetting(string path) { //либо создаем коллекцию для накопления информации по алиасам сценариев List <XSearchObj> scenAliasList = new List <XSearchObj>(); using (XmlReader xml = XmlReader.Create(path)) { while (xml.Read()) { switch (xml.NodeType) { case (XmlNodeType.Element): //нашли элемент step и в нем атрибут MainMenu if (xml.Name == "step" && xml.GetAttribute("name") == "MainMenu") { XmlReader mainMenuNode = xml.ReadSubtree(); while (mainMenuNode.Read()) { // нашли элемент menuitem и избавляемся от оболочек в меню с type="1", которые скрывают реальные услуги if (mainMenuNode.Name == "menuitem" && xml.HasAttributes && xml.GetAttribute("type") == "0") { string scen_alias = null, service_alias = null; scen_alias = xml.GetAttribute("alias"); service_alias = xml.GetAttribute("service_alias"); fillXmlItem(true, ref scenAliasList, ref scen_alias, ref service_alias); } } mainMenuNode.Close(); } // нашли элемент scenario if (xml.Name == "scenario" && xml.HasAttributes) { string scen_alias = null; scen_alias = xml.GetAttribute("alias"); if (scen_alias.Length != 0) { XSearchObj fromScenario = new XSearchObj(); fromScenario.scen_alias = scen_alias.ToCharArray(); //так как service_alias пуст, добавим в service_alias псевдоним сценария fromScenario.alias = scen_alias.ToCharArray(); //добавление в коллекцию LuceneIndex либо в коллекцию scenAliasList.Add(fromScenario); } } // нашли элемент scenarioIntricate if (xml.Name == "scenarioIntricate" && xml.HasAttributes) { string serv_alias = null, scen_alias = null; serv_alias = xml.GetAttribute("name"); scen_alias = xml.GetAttribute("alias"); fillXmlItem(false, ref scenAliasList, ref serv_alias, ref scen_alias); } //нужно бросить исключение что ничего не найдено??? break; } } } return(scenAliasList); }