Автор | Сообщение |
|
| |
Пост 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... напрягает....
|
|
|
Ответов - 120
, стр:
1
2
3
4
5
6
All
[только новые]
|
|
|
| |
Пост N: 3731
Зарегистрирован: 17.05.05
|
|
Отправлено: 23.11.13 19:42. Заголовок: Andrey пишет: Жду о..
Andrey пишет: Андрей выше чуть я давал пример как раз на несколько полей и BM фильтром.
|
|
|
|
| постоянный участник
|
Пост N: 3112
Зарегистрирован: 12.09.06
|
|
Отправлено: 23.11.13 20:41. Заголовок: Dima пишет: Андрей ..
Dima пишет: цитата: | Андрей выше чуть я давал пример как раз на несколько полей и BM фильтром. |
| у меня в тесте, несколько сложнее поиск. (В базе 12 полей FAM1-FAM12, NAME1-NAME12, OTCH1-OTCH12) По одному полю делать понятно как. А как делать в моем случае ? Прими участие в составление теста !
|
|
|
|
| |
Пост N: 3732
Зарегистрирован: 17.05.05
|
|
Отправлено: 23.11.13 20:47. Заголовок: Andrey пишет: По од..
Andrey пишет: цитата: | По одному полю делать понятно как. |
| Там чуть ниже есть пример для 3-х полей (то же самое сделать можно для 12 полей) ПС Ключевое слово в сообщении CrazyFilter
|
|
|
|
| постоянный участник
|
Пост 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.
|
|
|
|
| постоянный участник
|
Пост N: 264
Зарегистрирован: 17.02.12
|
|
Отправлено: 24.11.13 12:42. Заголовок: Andrey После dbEvalD..
Andrey После dbEvalDirect(), без BM фильтра можно положить, полученный массив в dbf MEMIO (если не проходит массив в browse, как писал Pasha) и на него browse, добавив в skipper перемещение на нужную RecNo в основном алисе (как писал Dima) и ВСЕ старое должно заработать.
|
|
|
|
| постоянный участник
|
Пост N: 3113
Зарегистрирован: 12.09.06
|
|
Отправлено: 24.11.13 13:28. Заголовок: SergKis Спасибо БОЛЬ..
SergKis Спасибо БОЛЬШОЕ !
|
|
|
|
| Администратор
|
Пост N: 3050
Зарегистрирован: 23.05.05
|
|
Отправлено: 24.11.13 22:16. Заголовок: Andrey пишет: dbEva..
Andrey пишет: цитата: | dbEvalDirect() - не работает, слишком большое условие поиска (больше 900 символов). Павел, если можно сделать большую строку поиска, то очень хорошо, если нет, то не страшно. |
| Что еще за строка символов ? 2-й параметр - это блок кода, который должен вернуть логическое значение. Точно так же, как и в dbEval().
|
|
|
|
| |
Пост N: 3733
Зарегистрирован: 17.05.05
|
|
Отправлено: 24.11.13 23:26. Заголовок: Pasha Он не пытаетс..
Pasha Он не пытается понять что пишут мне кажется.............подавай готовый код и тд и тп , возможно устал
|
|
|
|
| постоянный участник
|
Пост 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) Может я неправильно описал ? Извиняюсь за своё косноязычее....
|
|
|
|
| постоянный участник
|
Пост 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()
|
|
|
|
| |
Пост N: 3734
Зарегистрирован: 17.05.05
|
|
Отправлено: 25.11.13 09:01. Заголовок: Andrey пишет: Но по..
Andrey пишет: цитата: | Но почему то не получается как у тебя: RDDSETDEFAULT( "BMDBFCDX" ) |
| Harbour ?
|
|
|
|
|
| постоянный участник
|
Пост N: 3116
Зарегистрирован: 12.09.06
|
|
Отправлено: 25.11.13 09:06. Заголовок: Dima пишет: Harbour..
|
|
|
|
| |
Пост 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
|
|
|
|
| |
Пост 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 ФИО в одной записи... Точно от этого никак не избавиться ?
|
|
|
|
| постоянный участник
|
Пост N: 3117
Зарегистрирован: 12.09.06
|
|
Отправлено: 25.11.13 11:13. Заголовок: Sergy пишет: Точно ..
Sergy пишет: цитата: | Точно от этого никак не избавиться ? |
| Было так заведено... году так в 1998 ... Тогда мемо поля пропадали и не было Харбора, а только Клипер. Пришлось извратиться... Sergy пишет: цитата: | какая задача может потребовать столь чудовищной структуры данных - 12 ФИО в одной записи... |
| Приватизация жилья. 12 полей Фамилий + 12 полей Имен + 12 полей Отчеств на ОДНУ запись ! Живет и работает программа со свистом... : Стоит ли переделывать рабочую программу, если поиск сейчас занимает 01 сек ?
|
|
|
|
| постоянный участник
|
Пост 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 сек. Многовато будет....
|
|
|
|
| постоянный участник
|
Пост N: 3119
Зарегистрирован: 12.09.06
|
|
Отправлено: 25.11.13 11:42. Заголовок: Dima пишет: Вот жив..
Dima пишет: цитата: | Вот живой пример (фильтр по 3-м полям) для HARBOUR (В Иксах не проверял так как их нет у меня) |
| Нет в хХарборе HB_REGEXHAS Чем можно заменить ?
|
|
|
|
| |
Пост N: 3736
Зарегистрирован: 17.05.05
|
|
Отправлено: 25.11.13 11:44. Заголовок: Andrey пишет: Нет в..
|
|
|
|
| |
Пост 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("ИВАНОВ","ИВАН","ИВАНОВИЧ")} Дай погудю немного: Скрытый текст Andrey пишет:
цитата: | Приватизация жилья. 12 полей Фамилий + 12 полей Имен + 12 полей Отчеств на ОДНУ запись ! Живет и работает программа со свистом... : Стоит ли переделывать рабочую программу, если поиск сейчас занимает 01 сек ? |
|
Ниче не нужно переделывать. Все наши проги работают лучше всех, несмотря на классический пример неправильной структуры данных. В одной приватизации может участвовать два человека, в другой - три, а десяток пустых ФИО (т.е. примерно тридцать полей) будут болтаться в записи... А если нужно будет приватизировать одну жилплощадь на 13 человек - одного придется обломать... А потом возникают "спасите-помогите, строка поиска занимает килобайт и препроцессор/макрокомпилер не может ее проглотить..."
|
|
|
|
|
| Администратор
|
Пост 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)
|
|
|
Ответов - 120
, стр:
1
2
3
4
5
6
All
[только новые]
|
|