On-line: гостей 0. Всего: 0 [подробнее..]
АвторСообщение





Пост N: 368
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 08.11.13 13:41. Заголовок: DBFNTX: как грамотно прервать работу SET FILTER ?


Добрый день

Есть некая таблица:
date D8
idx1 N5
idx2 N5
flags C5
string C80

И есть фрагмент программы:
filter_sx := "" 
SELE table
SET FILT TO IIF(LEN(filter_sx)==0,TRUE,(filter_sx $ table->str))
DBEDIT(...)

Т.е. пока в строку фильтра ничего не попало - видны все записи.
Если юзер хочет отфильтровать часть записей по содержимому строки - срабатывает фильтр.

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

Делал так:
filter_sx := "" 
SELE table
SET FILT TO MyFilter()
DBEDIT(...)
...

FUNC MyFilter()

IF LEN(filter_sx) == 0
RETURN TRUE
ELSEIF INKEY(0) == K_ESC // юзер устал ждать ?
filter_sx := "" // выключаем фильтр
RETURN TRUE
ELSE
RETURN (filter_sx $ table->string)
ENDIF
RETURN TRUE

Но данный метод приводит вообще к чудным результатам: в 90% случаев после нажатия Esc - DBEDIT() начинает бешено прокручивать список вверх и зависает на первом элементе таблицы. Насколько понял по отладчику, что-то непонятное (для меня) происходит в недрах объекта в районе :Stabilize()

С какой стороны к этому вопросу подступиться?

PS: в Clipper было тоже самое - но когда тормозило всё, это было не так заметно, а сейчас, на фоне быстрой и адекватной работы Harbour... напрягает....

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 120 , стр: 1 2 3 4 5 6 All [только новые]


администратор




Пост N: 3731
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 23.11.13 19:42. Заголовок: Andrey пишет: Жду о..


Andrey пишет:

 цитата:
Жду от Димы.


Андрей выше чуть я давал пример как раз на несколько полей и BM фильтром.


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3112
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 23.11.13 20:41. Заголовок: Dima пишет: Андрей ..


Dima пишет:

 цитата:
Андрей выше чуть я давал пример как раз на несколько полей и BM фильтром.


у меня в тесте, несколько сложнее поиск. (В базе 12 полей FAM1-FAM12, NAME1-NAME12, OTCH1-OTCH12)
По одному полю делать понятно как. А как делать в моем случае ?
Прими участие в составление теста !

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 3732
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 23.11.13 20:47. Заголовок: Andrey пишет: По од..


Andrey пишет:

 цитата:
По одному полю делать понятно как.


Там чуть ниже есть пример для 3-х полей (то же самое сделать можно для 12 полей)

ПС
Ключевое слово в сообщении CrazyFilter

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 263
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 24.11.13 12:29. Заголовок: Andrey пишет:dbEvalD..


Andrey пишет:
 цитата:
dbEvalDirect() - не работает, слишком большое условие поиска (больше 900 символов)


Зачем так мучить выражение, можно (разбив на части и поместив в массив) примерно так:
 
FUNC MyFltr( aBlock )
LOCAL i
FOR i := 1 TO len(aBlock)
IF ! EVal(aBlock[ i ]
RETURN .F.
ENDIF
NEXT
RETURN .T.


Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 264
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 24.11.13 12:42. Заголовок: Andrey После dbEvalD..


Andrey
После dbEvalDirect(), без BM фильтра можно
положить, полученный массив в dbf MEMIO (если не проходит массив в browse, как писал Pasha) и на него browse, добавив в skipper перемещение на нужную RecNo в основном алисе (как писал Dima) и ВСЕ старое должно заработать.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3113
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 24.11.13 13:28. Заголовок: SergKis Спасибо БОЛЬ..


SergKis Спасибо БОЛЬШОЕ !

Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 3050
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 24.11.13 22:16. Заголовок: Andrey пишет: dbEva..


Andrey пишет:

 цитата:
dbEvalDirect() - не работает, слишком большое условие поиска (больше 900 символов).
Павел, если можно сделать большую строку поиска, то очень хорошо, если нет, то не страшно.



Что еще за строка символов ? 2-й параметр - это блок кода, который должен вернуть логическое значение. Точно так же, как и в dbEval().

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 3733
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 24.11.13 23:26. Заголовок: Pasha Он не пытаетс..


Pasha
Он не пытается понять что пишут мне кажется.............подавай готовый код и тд и тп , возможно устал

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3114
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 00:37. Заголовок: Pasha пишет: func ..


Pasha пишет:

 цитата:
Что еще за строка символов ? 2-й параметр - это блок кода, который должен вернуть логическое значение. Точно так же, как и в dbEval().


Pasha пишет выше:

 цитата:

func main
Local bFor := {|| "Охрана"$Otkomu}
Local bDo := {|| nk ++}
........
dbEvalDirect(bDo, bFor)
..........



В моем случае:
cFilterTo:= '("ИВАНОВ"$UPPER(FAM1).AND."ИВАН"$UPPER(NAME1).AND."ИВАНОВИЧ"$UPPER(OTCH1)).OR.("ИВАНОВ"$UPPER(FAM2).... ' - и т.д. Длина строки поиска=956 символов
FUNCTION MyFindEvalDirect(cFilterTo,cFio)
Local bDo := {|| AADD(aRecs, RECNO()) }
Local bFilter := {|| cFilterTo }
......
dbEvalDirect(bDo, bFilter)

Может я неправильно описал ? Извиняюсь за своё косноязычее....

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3115
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 00:40. Заголовок: Dima пишет: Он не п..


Dima пишет:

 цитата:
Он не пытается понять что пишут мне кажется.............подавай готовый код и тд и тп , возможно устал


Да пытаюсь понять и сделать применительно к своей задаче. Из-за этого и отдельный пример сделал.
Устал, это точно.
Разбираюсь с твоим CrazyFilter....

У меня в тесте - LOCATE отрабатывает за 0,01 сек. (удивительно быстро..., всегда считал его медленным)
Там код вот такой есть:
DBSETORDER(0)
LOCATE FOR &cFilterTo
DO WHILE Found() // help xHarbour Language Reference Guide
nRec++
AADD( aRecno, RECNO() ) // записать в массив
CONTINUE
ENDDO


Но почему то не получается как у тебя:
RDDSETDEFAULT( "BMDBFCDX" )
SELECT DOGOVOR
BM_DBSETFILTERARRAY(aRecno)
BROWSE()

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 3734
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 25.11.13 09:01. Заголовок: Andrey пишет: Но по..


Andrey пишет:

 цитата:
Но почему то не получается как у тебя:
RDDSETDEFAULT( "BMDBFCDX" )


Harbour ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3116
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 09:06. Заголовок: Dima пишет: Harbour..


Dima пишет:

 цитата:
Harbour ?


хХарбор 1.2.3
Пример здесь - выше. Исправленных файл из проекта. http://files.mail.ru/0FB87DC650FA43E0969EB86D82B447A0


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 3735
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 25.11.13 09:36. Заголовок: Andrey Вот живой пр..


Andrey
Вот живой пример (фильтр по 3-м полям) для HARBOUR (В Иксах не проверял так как их нет у меня)
 
#include "dbinfo.ch"
REQUEST BMDBFNTX
Proc main()
FIELD F1,F2,F3
RDDSETDEFAULT( "BMDBFNTX" )
cls
aeval(directory("tst.*"),{|x|ferase(x[1])})
dbCreate("tst", {{"F1", "C", 20, 0},{"F2", "c", 20, 0},{"F3", "c", 20, 0}})
USE tst
while lastrec()<100000
dbappend()
F1:= strzero(recno(),10)+chr(recno()%26+asc("A"))
F2:= strzero(recno(),10)+chr(recno()%26+asc("B"))
F3:= strzero(recno(),10)+chr(recno()%26+asc("C"))
enddo
INDEX ON F1 TO tst1
INDEX ON F2 TO tst2 additive
INDEX ON F3 TO tst3 additive

if CrazyFilter({{1,".*101.*A"},{2,".*101.*B"},{3,".*101.*C"}})
browse()
else
? "Нет подходящих записей"
endif

return




******************
Func CrazyFilter(par)
local i
local amas
local cRegex
local ret:=.t.

for i=1 to len(par)
amas:={}
if !empty(par[ i ][2])
cRegex:=par[ i ][2]
cRegex:=HB_REGEXCOMP(cRegex)
dbsetorder(par[ i ][1])
dbgotop()
while !eof()
if HB_REGEXHAS(cRegEx,ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPREGEX,,,cRegex)
enddo
BM_DBSETFILTERARRAY(amas)
endif
next
if len(amas)==0
dbclearfilter()
ret:=.f.
endif

return ret




Сборка c:\hb32\bin\hbmk2 t -lrddbm

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 380
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 25.11.13 10:53. Заголовок: Andrey пишет: В мое..


Andrey пишет:

 цитата:
В моем случае:
cFilterTo:= '("ИВАНОВ"$UPPER(FAM1).AND."ИВАН"$UPPER(NAME1).AND."ИВАНОВИЧ"$UPPER(OTCH1)).OR.("ИВАНОВ"$UPPER(FAM2).... ' - и т.д.



Не очень понимаю, какая задача может потребовать столь чудовищной структуры данных - 12 ФИО в одной записи...
Точно от этого никак не избавиться ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3117
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 11:13. Заголовок: Sergy пишет: Точно ..


Sergy пишет:

 цитата:
Точно от этого никак не избавиться ?


Было так заведено... году так в 1998 ...
Тогда мемо поля пропадали и не было Харбора, а только Клипер.
Пришлось извратиться...
Sergy пишет:

 цитата:
какая задача может потребовать столь чудовищной структуры данных - 12 ФИО в одной записи...


Приватизация жилья. 12 полей Фамилий + 12 полей Имен + 12 полей Отчеств на ОДНУ запись !
Живет и работает программа со свистом... :
Стоит ли переделывать рабочую программу, если поиск сейчас занимает 01 сек ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3118
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 11:39. Заголовок: Тесты на сетке: Пут..


Тесты на сетке:
Путь к БД: \\SERVERXP\DBF-Search\DBF\
Инфо о БД: Кол-во записей в БД = 101000 OS: Windows 8 Professional 6.02.9200

ВСЕГО ЗАТРАЧЕНО на поиск (SET FILTER) = 01 мин. 47 сек.
ВСЕГО ЗАТРАЧЕНО на поиск (Locate) = 29 сек.

Многовато будет....



Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3119
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 11:42. Заголовок: Dima пишет: Вот жив..


Dima пишет:

 цитата:
Вот живой пример (фильтр по 3-м полям) для HARBOUR (В Иксах не проверял так как их нет у меня)



Нет в хХарборе HB_REGEXHAS
Чем можно заменить ?

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 3736
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 25.11.13 11:44. Заголовок: Andrey пишет: Нет в..


Andrey пишет:

 цитата:
Нет в хХарборе HB_REGEXHAS
Чем можно заменить ?


http://clipper.borda.ru/?1-4-0-00000939-000-0-0-1383983897

Спасибо: 0 
ПрофильЦитата Ответить





Пост N: 381
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 25.11.13 11:57. Заголовок: Дай погудю немного: ..


Как вариант - сделать примерно так:

FUNC MyFilter(cName1,cName2,cName3) 
LOCAL i,result
result := FALSE
FOR i:=1 TO 12
IF cName1 $ &("FAM"+NTRIM(i)) .AND. ;
cName2 $ &("NAME"+NTRIM(i)) .AND. ;
cName3 $ &("OTCH"+NTRIM(i))
result := TRUE
EXIT
NEXT i
RETURN result

А если нехота использовать макросы, можно получить доступ через FIELDPOS() - если записей очень много, есть подозрение что он будет работать быстрее. Только нужно определиться, в каком порядке идут имена, отчества и фамилии. И в последствии постараться не менять структуру.

А потом уже фильтровать на основании блока кода {|| MyFilter("ИВАНОВ","ИВАН","ИВАНОВИЧ")}

Дай погудю немного:
Скрытый текст



Спасибо: 0 
ПрофильЦитата Ответить
Администратор




Пост N: 3051
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 25.11.13 19:21. Заголовок: Andrey пишет: В мое..


Andrey пишет:

 цитата:
В моем случае:
cFilterTo:= '("ИВАНОВ"$UPPER(FAM1).AND."ИВАН"$UPPER(NAME1).AND."ИВАНОВИЧ"$UPPER(OTCH1)).OR.("ИВАНОВ"$UPPER(FAM2).... ' - и т.д. Длина строки поиска=956 символов
FUNCTION MyFindEvalDirect(cFilterTo,cFio)
Local bDo := {|| AADD(aRecs, RECNO()) }
Local bFilter := {|| cFilterTo }
......
dbEvalDirect(bDo, bFilter)

Может я неправильно описал ? Извиняюсь за своё косноязычее....



Не буду даже пытаться объяснить, что к чему, просто покажу, как надо сделать:
// Создание блока кода из выражения поиска
bFilter := &("{||" + cFilterTo + "}")
......
dbEvalDirect(bDo, bFilter)


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 120 , стр: 1 2 3 4 5 6 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 8
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет