Exemple #1
0
        //ищем услугу в индексе. что ищем (queryString) и в каком поле (Field)
        //TODO: переделать на поиск по множеству полей и выдачу нужных полей (передача SearchObject?)
        public List <XSearchObjJSON> Search(string queryString)
        {
            lock (searchLock)
            {
                IndexReader   reader   = IndexReader.Open(_catalogPath, true); //ReadOnly = true для производительности
                IndexSearcher searcher = null;

                try
                {
                    //создаем список JSON объектов для сериализации
                    List <XSearchObjJSON> xsearchObjList = new List <XSearchObjJSON>();

                    //Создадим IndexSearcher
                    searcher = new IndexSearcher(reader);

                    //Если в строке поиска меньше символов чем нужно, то кидаем сообщение в UI
                    if (queryString.Length < minSymbPerSearch)
                    {
                        //придумать коды ошибок, чтобы уже на UI возвращать ошибку в нужном языке langData.lbl_search_not_found_message[lang]
                        xsearchObjList.Add(new XSearchObjJSON("error001"));
                        //удаляем Searcher и Reader;
                        searcher.Dispose();
                        reader.Dispose();
                        return(xsearchObjList);
                    }

                    // Строим Query объект
                    //****************************************************************************************
                    // Внимание!!! добавляем "*" согласно синтаксу Lucene ищет вхождения по всему индексированномоу тексту
                    //****************************************************************************************
                    Regex lucenePattern = new Regex(LUCENE_ESCAPE_CHARS);

                    string escapedQuery = queryString;
                    //escapedQuery = lucenePattern.Replace(queryString, REPLACEMENT_STRING);
                    //string escapedQuery1 = Regex.Replace(escapedQuery, @"\\", @"\");
                    //escapedQuery = Helper.RemoveDuplicateCharsFast(escapedQuery, '\\');


                    QueryParser parser = new QueryParser(Version.LUCENE_30, SearchField, analyzer);

                    //BooleanQuery q = new BooleanQuery();



                    //разершаем поиск вида "*кредит"
                    parser.AllowLeadingWildcard = true;

                    /*устанавливаем поиск вхождения по всем термам term1 AND term2 AND... QueryParser.AND_OPERATOR
                     * (исправляет кейс ниже)
                     * Шаги воспроизведения:
                     * 1.	Ввести «моя креди» и нажать на кнопку Далее
                     * Актуальный результат:
                     * Найдена только услуга «Моя кредитная история»
                     * Ожидаемый результат:
                     * Найдены услуги имеющие либо слово моя либо слово креди
                     */

                    parser.DefaultOperator = QueryParser.AND_OPERATOR;

                    /* но если требуется вхождение по "инн 1" всех "инн 102, инн 101233"
                     * то придется убрать либо ставить QueryParser.OR_OPERATOR
                     */

                    //parser.DefaultOperator = QueryParser.OR_OPERATOR;

                    //Query query = parser.Parse(QueryParser.Escape(queryString)+"*");
                    Query query = parser.Parse(escapedQuery + '*');


                    //Query query = parser.Parse(queryString);


                    // Search for the query
                    TopScoreDocCollector collector = TopScoreDocCollector.Create(maxHitsPerSearch, false);
                    searcher.Search(query, collector);

                    ScoreDoc[] hits = collector.TopDocs().ScoreDocs;

                    int hitCount = hits.Length;


                    if (hitCount == 0)
                    {
                        //Console.WriteLine("Совпадений для \"" + queryString + "\" не найдено");
                        //пример сообщения для ui
                        //xsearchObjList.Add(new XSearchObjJSON("Услуги не найдены"));
                    }
                    else
                    {
                        //Console.WriteLine("Совпадений для \"" + queryString + "\" найдено:");

                        // Ищем по всем документам в индексе
                        for (int i = 0; i < hitCount; i++)
                        {
                            ScoreDoc scoreDoc = hits[i];
                            int      docId    = scoreDoc.Doc;
                            //float docScore = scoreDoc.Score;

                            Document doc = searcher.Doc(docId);

                            //вытаскиваем все поля и создаем объект для сериализации

                            string logo = (doc.Get(Helper.GETNAME(new { read_xsobj_field.logo })) == String.Empty || doc.Get(Helper.GETNAME(new { read_xsobj_field.logo })) == null) ?
                                          String.Empty : doc.Get(Helper.GETNAME(new { read_xsobj_field.logo }));

                            if (!Path.HasExtension(logo))
                            {
                                logo = logo + imagesExtention;
                            }

                            XSearchObjJSON temp = new XSearchObjJSON(doc.Get(Helper.GETNAME(new { read_xsobj_field.id_service })),
                                                                     doc.Get(Helper.GETNAME(new { read_xsobj_field.alias })),
                                                                     doc.Get(Helper.GETNAME(new { read_xsobj_field.scen_alias })), doc.Get(Helper.GETNAME(new { read_xsobj_field.name_service })),
                                                                     logo);

                            //ничего не пишем в сообщения
                            temp.message = string.Empty;



                            //добавляем объекты удачного поиска для сериализации
                            xsearchObjList.Add(temp);
                        }
                    }

                    //удаляем Searcher и Reader;
                    searcher.Dispose();
                    reader.Dispose();

                    //return json;
                    return(xsearchObjList);
                }
                catch (Exception ex)
                {
                    if (ex is ParseException || ex is IOException || ex is NullReferenceException)
                    {
                        //удаляем Searcher и Reader???
                        if (searcher != null)
                        {
                            searcher.Dispose();
                        }
                        reader.Dispose();
                        //сообщаем об ошибках наружу
                    }
                    throw;
                }
            }
        }
Exemple #2
0
        //ищем в индексе услуги по 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);
            }
        }