• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Ftsearchrange не охватывает все документы

  • Автор темы Akupaka
  • Дата начала
A

Akupaka

Всем привет!
Есть вопрос по FTSearchRange, может кто юзал и с опытом ткнет меня носом туда, где я промахнулся? :(
Ниже представлен код, который выбирает не все документы.
Например, документов подходящих под условие поиска 27738, а код обрабатывает за первый запуск 15102, за второй - 12636.
Во втором случае, из 39344 за первый раз обработалось 24150 дока, а за второй - 15194.
Т.е. обрабатывается не все, при чем, каждый раз по-разному. Исходя из этого, я предполагаю, что проблема не в логике кода, но могу и ошибаться.

Код:
	Public Function ArchiveByRule(ASearchRule As String, ARuleType As Integer) As Integer
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Dim sstart As Long
Dim scount As Long
Dim colcount As Long
ArchiveByRule = False
If Me.isInit() And checkArchiveAccess() And (ASearchRule <> "") Then
Select Case ARuleType
Case 1 ' @Formula search
Set col = mMainDb.Search(ASearchRule, Nothing, 0)
ArchiveByRule = doArchiveCol(col)

Case 2 ' FTSearch
ArchiveByRule = True
scount = 1000
sstart = 1
Set col = mMainDb.FTSearchRange(ASearchRule, scount, FT_SCORES, , sstart)
colcount = col.Count
While colcount > 0
ArchiveByRule = ArchiveByRule And doArchiveCol(col)
sstart = sstart + scount
If colcount < scount Then
colcount = 0
Else
Set col = mMainDb.FTSearchRange(ASearchRule, scount, FT_SCORES, , sstart)
colcount = col.Count
End If
Wend

End Select
End If
End Function

doArchiveCol() - фактически проходит по коллекции и удаляет документы из базы, и возвращает булевое значение (тру, если все хорошо).

заранее спасибо! :(
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
как много букффф
может ФТиндекс не обновлен или на нем ограничение, по возврату максимум Х доков? :(
 
A

Akupaka

Тоху отправляем читать доки, они рулез ;)

индекс обновлен перед запуском, а про метод посмотри справку.

хотя, у меня есть одно подозрение, но пока не могу проверить, база большая, внешние задачи отвлекают ее от работы со мной ))
 
T

TIA

Не знаю, исправили сейчас или нет, а раньше был такой вот баг. Св-во count тупо выставлялось равным заданному через параметр (scount). А getFirstDocument/getNextDocument при этом выскр*цензура*и из коллекции гораздо больше документов, чем в count обещано.
 
A

Akupaka

Не знаю, исправили сейчас или нет, а раньше был такой вот баг
именно этот баг не наблюдается, что показало логирование кода.
но почему оно не продолжает искать дальше не могу понять. ни сообщений об ошибках, ничего. просто, в какой-то момент возвращает не полную коллекцию, а только часть, ну а алгоритм подразумевает, что это последний поиск.
интересно... надо бы еще проверить, что вернет поиск после "последнего" поиска.
 
H

hosm

я как-то тебе пример давала с другой организацией цикла? попробуй перепиши для проверки код немного по-другому, чтоб вызывать поиск дальше, проверив коллекцию и потом первый док на Nothing. Я в таком варианте на 7-ке тестила немного, вроде всё находило корректно. Ну, и девченки на 8.5 проверяли. конечно, не в твоих масштабах =) и ошибок, описанных ребятами, не находили, может, их таки поправили.
Были какие-то глюки при подсчете кол-ва доков в другом месте при поиске в 8.5.0, но, возможно, там из-за ограничения доступа, так как под админом на 7/8.5 и под всеми на 7-ке работало корректно - пока ошибку отложили, не разбиралась еще...

сервер у нас стоял 7.0.3 или 7.0.2 - точно не помню.
 
A

Akupaka

кто мне покажет где я тупка, тому пряник! :welcome:

есть простой код для поиска:
<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">Код ТУТ</div></div><div class="sp-body"><div class="sp-content">
Код:
	Dim ws As New NotesUIWorkspace
Dim s As New NotesSession
Dim searchDb As NotesDatabase
Dim paramDoc As NotesDocument
Dim tmpDoc As NotesDocument
Dim ftQuery As String
Dim ftSearchCol As NotesDocumentCollection
Dim resultCol As NotesDocumentCollection
Dim sstart As Long
Dim scount As Long
Dim colcount As Long

Set paramDoc = ws.CurrentDocument.Document
ftQuery = paramDoc.GetItemValue("Query")(0)
Set searchDb = Nothing 'GetSearchDb(...)
If searchDb.IsOpen() Then
scount = 5000
sstart = 1
Stop
Do
Set ftSearchCol = searchDb.FTSearchRange(ftQuery, scount, FT_SCORES, , sstart)
colcount = ftSearchCol.Count
Print Now & ": ftSearchCol.Count: " & Cstr(colcount)
If colcount > 0 Then
sstart = sstart + scount
If resultCol Is Nothing Then
Set resultCol = ftSearchCol
Else
Set tmpDoc = ftSearchCol.GetFirstDocument
While Not(tmpDoc Is Nothing)
Call resultCol.AddDocument(tmpDoc)
Set tmpDoc = ftSearchCol.GetNextDocument(tmpDoc)
Wend
End If
End If
Loop While colcount > 0

If Not(resultCol Is Nothing) Then
colcount = resultCol.Count
Else
colcount = 0
End If
Print Now & ": resultCol.Count: " & Cstr(colcount)
Call paramDoc.ReplaceItemValue("ResultCount", Cstr(colcount))
Msgbox "The End"
End If


если
ftQuery = { [adate]=01.07.2008 and ([Form]=FormA) }
результатом будет 16879 документов

если
ftQuery = { [adate]=01.07.2008 and ([Form]=FormB) }
результатом будет 17854 документа

если
ftQuery = { [adate]=01.07.2008 and ([Form]=FormC) }
результатом будет 743 документа

в сумме 35476 документов! и это правильно, потому что в виде, который отбирает по формам FormA, FormB и FormC, и, группирует документы по дате, их столько и в категории и отображается.
к стати, если задать
ftQuery = { [adate]=01.07.2008 }
то результатом будет тоже 35476.

но! вот, если я задаю запрос так
ftQuery = { [adate]=01.07.2008 and ([Form]=FormA or [Form]=FormB or [Form]=FormC) }
то результатом будет не 35476, а 17622 документов!

где суслик?! О.о ;)
 
O

Omh

Akupaka
А почему не хочешь забанить FTSearch?
У тебя же жёсткие условия поиска, почему бы не искать через просто Search?
Он работает, как часы.

P.S. Хотя ответ, конечно, не совсем по теме. ;)
 
A

Akupaka

А почему не хочешь забанить FTSearch?
у меня база в которой за два года работы накопилось более 1.5 миллиона документов.
в одном месяце от 30 тыс. до 100 тыс. доков.
будет ли производительным использование Search вместо FTSearch?
хотя, если будут такие упадки со стороны FTSearch, то лучше потратить время, чем получить недостоверный результат.
но кто может подтвердить, что это закономерность в работе FTSearch?
 
S

Sandr

Не находишь странным то, что он тебе вернул доки по форме А и С, а В проигнорил? Может имеет место быть банальная ошибка в имени формы В?
 
T

turumbay

1.ftQuery = { [adate]=01.07.2008 and ([Form]=FormA) }
результатом будет 16879 документов
2.ftQuery = { [adate]=01.07.2008 and ([Form]=FormB) }
результатом будет 17854 документа
3.ftQuery = { [adate]=01.07.2008 and ([Form]=FormC) }
результатом будет 743 документа
в сумме 35476 документов!
4. ftQuery = { [adate]=01.07.2008 }
то результатом будет тоже 35476.

5. ftQuery = { [adate]=01.07.2008 and ([Form]=FormA or [Form]=FormB or [Form]=FormC) }
результатом будет 17622 документов
16879 + 743 = 17622. Это вряд ли случайно. Я лично не верю в такие совпадения :)
Т.е. запрос 1 + запрос 3 возвращает то же, что запрос 5
продолжаю наблюдение...
 
A

Akupaka

16879 + 743 = 17622. Это вряд ли случайно. Я лично не верю в такие совпадения
в ИТ волшебства не бывает. если не считать волшебством нашу глупость ;)
это не случайно, но это не поулчается понять.
мало того запрос с "[Form]=FormA or [Form]=FormB" возвращает только ту часть, что и просто запрос с "[Form]=FormA" О.о
но запрос с "[Form]=FormB" возвращает как надо
идиотизм!

короче, у кого есть желание поразбираться, прошу :welcome:

но выдам одну подсказку, которую мне подсказал хороший знакомый, даже два ;)
ftQuery = { [adate]=01.07.2008 and ([Form]=FormA , [Form]=FormB , [Form]=FormC) }
или
ftQuery = { [adate]=01.07.2008 and ([Form]=FormA,FormB,FormC) }
или
ftQuery = { [adate]=01.07.2008 and ([Form]=FormA or [Form]=FormB or [Form]=FormC) }
и
searchDb.FTSearchRange(ftQuery, scount, FT_DATECREATED_ASC, , sstart)

дают нужный результат :)
вот еще из хелпа:
Note ACCRUE (или ЗАПЯТАЯ) works slightly better than OR when sorting results by relevance (т.е. FT_SCORES).

но у меня тут проблема еще одна, что в некоторых случаях выпадает несколько документов, два-три. сейчас пытаюсь найти зависимость.

Добавлено:
но у меня тут проблема еще одна, что в некоторых случаях выпадает несколько документов, два-три. сейчас пытаюсь найти зависимость.
проблема найдена! :)
некоторые документы хранят нужную дату не первого числа, хотя по задумке приложения должны были бы.
теперь все ищется! УРЯ!

Спасибо всем!
 
A

Akupaka

а что это вы мою тему так глубоко заборосили? еле нашел! ;)

интересует подтверждение решения.
задача: провести синхронное обновление FT-индекса базы.
т.е. есть код
Код:
	' some code before...
If db.Isftindexed Then
If db.Lastmodified > db.Lastftindexed Then
Call db.Updateftindex(False)
End If
End If

call db.FTSearch(...)
требуется, чтобы метод db.FTSearch был вызван на индексированной БД.
все хорошо работает, если БД локальная. при вызове данного кода, появляется окно прогресса, выполняется индексация, потом продолжает свое выполнение метод поиска.
в случае же, если БД на сервере, то метод db.Updateftindex не выполняет индексацию сразу, а, похоже, создает запрос на сервере на индексацию, если создает вообще. проблема в том, что при таком подходе db.FTSearch вызывается на неиндексированной БД.

я реализовал с помощью серверного агента. и после нескольких тестов у меня создалось впечатление, что это рабочий способ.
т.е. код преобразован так:
Код:
	' some code before...
call db.GetAgent("Reindex").RunOnServer()
' тут еще можно проверять результат выполнения агента, но не суть важно
call db.FTSearch(...)
код агента:
Код:
Sub Initialize()
Dim s As New NotesSession
Dim db As NotesDatabase
Set db = s.Currentdatabase
If db.Isftindexed Then
If db.Lastmodified > db.Lastftindexed Then
Call db.Updateftindex(False)
End If
End If
End Sub

Прошу подтвердить либо опровергнуть способ реализации.
Заранее спасибо :)

на заметку.
практика показала, что иногда метод не срабатывает корректно, отбрасывает ошибку, что индекс занят.
причин не выяснил, да и не думаю, что получится )
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Akupaka
фигня как по мне
если у вас в индексе включно индексация аттача, ваш агент отлетит по таймауту ;)
 
A

Akupaka

если у вас в индексе включно индексация аттача, ваш агент отлетит по таймауту
не включено. но, как мне известно, по таймауту отлетают только те агенты, которые запущены amgr...
зы: можно на "ты", все-равно "Вы" с маленькой буквы пишешь ;)
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Akupaka
в любом случае считаю, что подталкивать фтиндексер это крайне экстримальное занятие :ya_za:
уж лучше обычный Search
 
A

Akupaka

уж лучше обычный Search
когда-то я уже отвечал на вопрос Омху, почему мне хочется использовать фт-поиск, а не бд-поиск

вот тебе разница в скорости работы фт- и дб-поиска :ya_za:

фт 88913 за 29,91015625 секунд
дб 88913 за 440,98046875 секунд
~14,74 раза дольше

вот еще резалт
фт 35476 за 13,109375 секунд
дб 35476 за 821,01953125 секунд
~63 раза дольше
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
Akupaka
я знаю про разницу
но у меня был негативный опыт, когда фтсечь чаще чем 5 раз в секунду юзать нельзя а надо
 
A

Akupaka

но у меня был негативный опыт, когда фтсечь чаще чем 5 раз в секунду юзать нельзя а надо
может что-то надо менять в себе? :RTFM:

на заметку.
практика показала, что иногда метод не срабатывает корректно, отбрасывает ошибку, что индекс занят.
причин не выяснил, да и не думаю, что получится )
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!