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





Пост 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: 74
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 08.11.13 14:30. Заголовок: Фильтр - через отдельный временный индекс


Построить временный индекс с индексным выражением , содержащим свою
функцию, которая реализует фильтр, бегунок создания и будет отслеживать реакцию юзера.
Если индекс построился, подключить его к базе.

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



Пост N: 75
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 08.11.13 14:38. Заголовок: Аналогично - copy to () for myFilter()


Аналогично - копирование таблицы по FOR-условию, которое содержит
фильтр, бегунок (для оценки юзером прогноза завершения)
Если копирование прошло без прерывания - переоткрыть обзор на новую таблицу
(отфильтрованная часть)

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





Пост N: 369
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 08.11.13 15:16. Заголовок: Ну так получится, чт..


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

Например: в table->string слово "Москва" встречается в каждой десятой записи. А слово "Якутия" - один раз на 2000 записей. В случае фильтра по "Москве" отфильтруется в среднем, 200 записей, чтобы 20 из них попали на экран. А для Якутии придется ждать, пока отфильтруется 40 тысяч записей.

В случае FOR-условий и тем более, постройки индекса во всех случаях придется ждать обработки всех >100 тыс. записей...

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




Пост N: 3037
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 08.11.13 16:04. Заголовок: Sergy пишет: FUNC ..


Sergy пишет:

 цитата:
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



Inkey(0) надо заменить на Inkey()
Ну и SetLastKey(0) перед фильтром не забыть поставить

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





Пост N: 370
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 08.11.13 16:53. Заголовок: Pasha пишет: Inkey(..


Pasha пишет:

 цитата:
Inkey(0) надо заменить на Inkey()


Ну да, разумеется. Пример писал по памяти. Общий смысл в том, что если юзер нажимает кнопку Esc - нужно выключить фильтр.


 цитата:
Ну и SetLastKey(0) перед фильтром не забыть поставить


Да, но к сожалению, это не повлияет на результат. DBEDIT() сходит с ума, если ему сначала функция фильтра выдавала FALSE, а потом на тех-же записях - неожиданно - TRUE...

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




Пост N: 3700
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 08.11.13 17:56. Заголовок: Как вариант можно по..


Как вариант можно по этому полю сделать индекс а затем с помощью DBOI_SKIPWILD или DBOI_SKIPREGEX выбрать номера записей и все потом загнать в BM фильтр , но боюсь что с NTX он не дружит.
Можно пример глянуть в Xharbour skipeval.prg , думаю он и в Harbour будет работать.

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




Пост N: 3067
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 08.11.13 19:05. Заголовок: Sergy пишет: процес..


Sergy пишет:

 цитата:
процесс фильтрации начинает занимать непозволительно долгое время


В Клипере 5.3 фильтр был оптимизирован, даже по сети у меня поиск летал.
При переходе на Харбор пришлось отказаться вообще от SET FILTER - по сетке всегда "тормоза", переделал все эти участки программы на условную индексацию.

Sergy пишет:

 цитата:
В случае FOR-условий и тем более, постройки индекса во всех случаях придется ждать обработки всех >100 тыс. записей...


Если уже есть готовое индексное выражение по одному ключу, то даже на базе 100 тыс. записей условная индексация строится МОМЕНТОМ !


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





Пост N: 371
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 08.11.13 19:58. Заголовок: Dima пишет: Как вар..


Dima пишет:

 цитата:
Как вариант можно по этому полю сделать индекс а затем с помощью DBOI_SKIPWILD или DBOI_SKIPREGEX выбрать номера записей и все потом загнать в BM фильтр , но боюсь что с NTX он не дружит.


Хм, почитал dbinfo.ch - идея занятная, нужно будет попробовать

Andrey пишет:

 цитата:
В Клипере 5.3 фильтр был оптимизирован, даже по сети у меня поиск летал.
При переходе на Харбор пришлось отказаться вообще от SET FILTER - по сетке всегда "тормоза", переделал все эти участки программы на условную индексацию.

Если уже есть готовое индексное выражение по одному ключу, то даже на базе 100 тыс. записей условная индексация строится МОМЕНТОМ !


Не очень понятно, если честно.
Вот есть таблица, пример в первом сообщении.
В строке длиной 80 символов юзер хочет найти ЛЮБОЕ нужное ему слово. А может быть, часть его. Оно может быть в начале, в середине и в конце строки. Как условная индексация сможет тут помочь ?

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




Пост N: 3068
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 08.11.13 23:53. Заголовок: Sergy пишет: Как ус..


Sergy пишет:

 цитата:
Как условная индексация сможет тут помочь ?


Держи индекс по этому полю всегда открытым.
SELECT table
// открыт файл с первым индексом по полю "string"
DBSETORDER(1)

Условная индексация тогда будет типа:
cSlovo := "моск"

cIndexTo := "'это поле индекса по базе для сортировки/ ставь сам любое поле"
cFileIndex := "table02.cdx"
cFilter := "cSlovo $ table->string .AND. !DELETED()" // можно еще условия поставить, допустим cSlovo1 и т.д.
DELETEFILE(cFileIndex) // всегда удаляю индекс (CDX) - так как налетаешь потом на грабли
SELECT table
DBSETORDER(1)
INDEX ON &cIndexTo TO (cFileIndex) FOR &cFilter
ORDLISTADD( cFileIndex )
// здесь в раб. область базы добавляется второй индекс
DbSetOrder(2)
nKolRecords := ORDKEYCOUNT() // кол-во найденых записей
TBROWSE() //или DBEDIT()

Поставь счетчик времени и увидишь сам быстродействие.



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



Пост N: 76
Зарегистрирован: 21.04.13
ссылка на сообщение  Отправлено: 09.11.13 00:05. Заголовок: А упростить схему можно?


В строке длиной 80 символов юзер хочет найти ЛЮБОЕ нужное ему слово...

Видимо, нужно по-другому организовать хранение данных..
полнотекстовый поиск - это не для NTX, это интернет поисковик какой-то

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




Пост N: 3069
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 09.11.13 11:34. Заголовок: Sergy пишет: Наприм..


Sergy пишет:

 цитата:
Например: в table->string слово "Москва" встречается в каждой десятой записи. А слово "Якутия" - один раз на 2000 записей.


petr707 пишет:

 цитата:
Видимо, нужно по-другому организовать хранение данных..


Наверно нужно делать просто справочник городов, а в базе хранить коды городов, тогда поиск будет просто "летать" !

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





Пост N: 372
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 09.11.13 12:55. Заголовок: Andrey пишет: полно..


Andrey пишет:

 цитата:
Видимо, нужно по-другому организовать хранение данных..
полнотекстовый поиск - это не для NTX, это интернет поисковик какой-то



Andrey пишет:

 цитата:
Наверно нужно делать просто справочник городов, а в базе хранить коды городов, тогда поиск будет просто "летать" !



поле table->string C80 содержит описание операции, которое формируется автоматически, но может быть скорректировано юзером.
Например:
При внутрискладском перемещении товара формируется запись: "цех -> отк" или "отк -> приемка"
При продаже товара: "магазин:Иванов (Петров)"
При поступлении: "склад << поставщик"
и тп.

к каждому этому описанию юзер может добавить что угодно, например: "/1=переделать документы", "проверить цены", "уточнить оплату" и тд и тп

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

Так что проиндексировать точно не получится и используется полнотекстовый поиск, "как в интернете...". Поэтому ищу способ грамотно выключить фильтрацию "на лету".

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




Пост N: 3072
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 09.11.13 13:03. Заголовок: Sergy пишет: Поэто..


Sergy пишет:

 цитата:
Поэтому ищу способ грамотно выключить фильтрацию "на лету".


Пробуй, что я предложил выше.

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





Пост N: 373
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 09.11.13 15:39. Заголовок: Andrey пишет: Пробу..


Andrey пишет:

 цитата:
Пробуй, что я предложил выше.



Andrey пишет:

 цитата:
Условная индексация тогда будет типа:
cSlovo := "моск"

cIndexTo := "'это поле индекса по базе для сортировки/ ставь сам любое поле"
cFileIndex := "table02.cdx"
cFilter := "cSlovo $ table->string .AND. !DELETED()" // можно еще условия поставить, допустим cSlovo1 и т.д.
DELETEFILE(cFileIndex) // всегда удаляю индекс (CDX) - так как налетаешь потом на грабли
SELECT table
DBSETORDER(1)
INDEX ON &cIndexTo TO (cFileIndex) FOR &cFilter


Один юзер хочет прямо сейчас найти "Моск", юзер на соседнем компе - "Якут" в тоже самое время.
Через минуту первому потребовалось "Санкт-П", а другому - "Казань". Через пару минут дальше - "Иваново". Третий юзер в тоже самое время начал искать "Владивосток".

Перестраивать индекс каждый раз?


 цитата:
Поставь счетчик времени и увидишь сам быстродействие


Понятно, что после создания индекса все "залетает"... Но так ведь его создать сначала нужно, те обработать >100 тыс записей. А это время, причем при всех вариантах - максимально долгое из возможных.

Или я что-то не так понял ?

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




Пост N: 3703
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 09.11.13 15:52. Заголовок: Sergy пишет: Так чт..


Sergy пишет:

 цитата:
Так что проиндексировать точно не получится и используется полнотекстовый поиск, "как в интернете...". Поэтому ищу способ грамотно выключить фильтрацию "на лету".



Забей на такую методу
Вот тебе живой пример и тормозов ни каких и все влет пашет.

 
#include "dbinfo.ch"
REQUEST BMDBFNTX
Proc main()
FIELD F1
local cPattern
local amas:={}
RDDSETDEFAULT( "BMDBFNTX" )

aeval(directory("_tst.*"),{|x|ferase(x[1])})
dbCreate("_tst", {{"F1", "C", 20, 0}})
USE _tst
while lastrec()<100000
dbappend()
F1 := strzero(recno(),10)+chr(recno()%26+asc("A"))
enddo
INDEX ON F1 TO _tst
dbcommit()

cPattern:="*101*A"
dbgotop()
if !eof() .and. ! WildMatch(cPattern, ordkeyval())
dborderinfo(DBOI_SKIPWILD,,,cPattern)
endif
while !eof()
if WildMatch(cPattern, ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPWILD,,,cPattern)
enddo
// а вот тут в своей проге ты можешь вернуться на нужный тебе индекс
BM_DBSETFILTERARRAY(amas)
browse()


return


или можно так и будет еще быстрее
 
cRegex:=".*101.*A"
cRegex:=HB_REGEXCOMP(cRegex)

dbgotop()
while !eof()
if HB_REGEXHAS(cRegEx,ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPREGEX,,,cRegex)
enddo
BM_DBSETFILTERARRAY(amas)
browse()





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





Пост N: 374
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 09.11.13 17:15. Заголовок: Dima пишет: REQUES..


Dima пишет:

 цитата:
REQUEST BMDBFNTX


Никогда не сталкивался с таким зверем. Погуглил на этом форуме и в интернете - мало информации.
Подтолкните в правильном направлении плиз.

Спасибо.


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




Пост N: 3704
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 09.11.13 17:35. Заголовок: Sergy Тема есть про..


Sergy
Тема есть про BMDBFCDX в твоем случае BMDBFNTX
http://clipper.borda.ru/?1-4-0-00000808-000-0-0-1363106357

А вообще harbour\contrib\rddbm\

ЗЫ
То есть если умалчиваемым RDD сделать BMDBFNTX то все будет работать как и работало но добавятся
новые возможности с BITMAP фильтрами.

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





Пост N: 375
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 09.11.13 19:13. Заголовок: Dima Спасибо, оказы..


Dima
Спасибо, оказывается, интересная штука! Пошел плотно изучать.



Может кому-то будет интересно - вот что надумал. Если нельзя менять SET FILTER "на лету", значит нужно проанализировать - откуда сейчас идет вызов.
 
filter_sx := ""
SELE table
SET FILT TO MyFilter()
DBEDIT(...)
...

FUNC MyFilter()
LOCAL ps:=ProcStack() // получаем стек процедур в виде строки

IF LEN(filter_sx) == 0
RETURN TRUE
ENDIF

IF INKEY() == K_ESC // юзер устал ждать ?
IF ("STAB" $ ps) .OR. ("SKIPPED" $ ps)
// СЕЙЧАС НЕЛЬЗЯ !
ELSE
filter_sx := "" // выключаем
RETURN TRUE
ENDIF
ENDIF

RETURN (filter_sx $ table->string)

Работает четко - вырубает фильтр без косяков.
Параллельно мониторю стек вызовов. Если окажется еще что-то, кроме "STABILIZE", "FORCESTABLE" и "SKIPPED", что приводит к зацикливанию - легко добавить в условие.

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




Пост N: 3074
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 10.11.13 06:30. Заголовок: Dima пишет: То есть..


Dima пишет:

 цитата:
То есть если умалчиваемым RDD сделать BMDBFNTX то все будет работать как и работало но добавятся
новые возможности с BITMAP фильтрами.


Если база открыта рабочей программой RDDCDX, можно ли открывать эту базу с помощью BMDBFCDX только для поиска ?
Косяков никаких не будет ?

И еще вопрос про поиск для BMDBFCDX:
Есть в базе поля FIO1, FIO2, FIO3 .... FIO12 (C 45)
Как организовать поиск сразу по всем полям ?
SET FILTER тормозит... Да и условие на 12 полей зашкаливает...

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




Пост N: 3705
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.11.13 13:27. Заголовок: Andrey пишет: Если ..


Andrey пишет:

 цитата:
Если база открыта рабочей программой RDDCDX, можно ли открывать эту базу с помощью BMDBFCDX только для поиска ?


А зачем так поступать. Сразу дефолтным делай BMDBFCDX , все будет работать как и работало + доп возможности с фильтрами.
А вообще если шибко надо то да можно открыть ту же базу в новой рабочей области с BMDBFCDX.
Потести в общем ;)

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




Пост N: 3706
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.11.13 15:20. Заголовок: Sergy пишет: ProcSt..


Sergy пишет:

 цитата:
ProcStack()


Самопал или либа нужна какая ?

Вероятно самопал что то типа
 
FUNC ProcStack()

LOCAL n := 0
Local ret:=""

WHILE ! Empty( ProcName( n ) )
ret+=" "+ProcName( n++ )
ENDDO

RETURN ret



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




Пост N: 3075
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 10.11.13 15:47. Заголовок: Dima Есть в базе по..


Dima
Есть в базе поля FIO1, FIO2, FIO3 .... FIO12 (C 45)
А индексы нужно делать тоже сразу по каждому полю ?
И как сделать поиск сразу по всем полям за один проход по базе ?
Набросай пожалуйста заготовку, как правильно это организовать.

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




Пост N: 3707
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 10.11.13 15:59. Заголовок: Заготовку не накидаю..


Заготовку не накидаю а вот идея как бы есть (развивай)
Да держим по каждому полю индекс что бы быстро отобрать нужные записи (но это дело вкуса)
Переключаемся на первый поисковый индекс и ищем как я выше описывал в примере.
Отобрали подходящие записи в массив и установили BM фильтр. Переключаемся на второй
поисковый индекс и повторяем процедуру поиска по этому полю собрав подходящие записи
в массив. Снимаем BM фильтр (вероятно можно и не снимать) и ставим новый и так далее. Теоретически должно работать быстро.
Чем дальше тем меньше записей будет попадать в обработку.

Пример
 
#include "dbinfo.ch"
REQUEST BMDBFNTX
Proc main()
FIELD F1,F2,F3
local cPattern,cRegex
local amas:={}
local nsec
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

nsec:=seconds()
cRegex:=".*101.*A"
cRegex:=HB_REGEXCOMP(cRegex)
dbsetorder(1)
dbgotop()
while !eof()
if HB_REGEXHAS(cRegEx,ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPREGEX,,,cRegex)
enddo
BM_DBSETFILTERARRAY(amas)

amas:={}
dbsetorder(2)
dbgotop()

cRegex:=".*510.*B"
cRegex:=HB_REGEXCOMP(cRegex)
dbgotop()
while !eof()
if HB_REGEXHAS(cRegEx,ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPREGEX,,,cRegex)
enddo
BM_DBSETFILTERARRAY(amas)

amas:={}
dbsetorder(3)
dbgotop()

cRegex:=".*510.*C"
cRegex:=HB_REGEXCOMP(cRegex)
dbgotop()
while !eof()
if HB_REGEXHAS(cRegEx,ordkeyval())
aadd(amas,recno())
endif
dborderinfo(DBOI_SKIPREGEX,,,cRegex)
enddo
BM_DBSETFILTERARRAY(amas)
? seconds()-nsec // 0.16 сек
wait
browse()

return



Вот такую функцию можно сделать
 
//CrazyFilter({{1,".*101.*A"},{2,".*101.*B"},{3,".*101.*C"}})
Func CrazyFilter(par)
local i
local amas
local cRegex

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

return nil



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



Пост N: 136
Зарегистрирован: 19.05.05
ссылка на сообщение  Отправлено: 10.11.13 16:54. Заголовок: Для этого лучше орга..


Для этого лучше организовать поиск по другому, ИМХО конечно. Заводится дополнительная база
из двух полей FIO C(45) NREC N(7) (к примеру, если записей в базе < 9999999 )
в базе индекс по FIO и NREC . Тогда не надо выполнять поиск по всем 12 индексам.
Выполнив один поиск по СЛОВУ получаем номера всех записей, у которых встречаются
заданное слово в любом из полей FIO1 - FIO12. Если необходимо выполнить поиск по нескольким словам
придется, естественно, выполнить пересечение. Усложнится ведение, так как при удалении записи из основной базы необходимо удалить все записи из дополнительной базы, при выполнении PACK перестроить
полностью всю базу, но такие процедуры как правило выполняются ночью или в выходные и это
по времени не критично. Но поиск будет быстрее. Это-же самое можно применить и для Sergy. Каждре слово из string писать отдельной записью. Естественно, будут ограничения, если есть слово АБВГД поиск можно выполнять по условию АБВ*, но не *БВГ*


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





Пост N: 376
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 10.11.13 17:54. Заголовок: Dima пишет: Самопал..


Dima пишет:

 цитата:
Самопал или либа нужна какая ?


 * ---------------------------------------- * 
FUNC ProcStack(nFrom,nTo,lNeedLines,cDefSep)

LOCAL i,res,sx,j
DEFAULT nFrom TO 1
DEFAULT nTo TO 40
DEFAULT lNeedLines TO FALSE
DEFAULT cDefSep TO ":"

res:=""
FOR i:=nFrom TO nTo
sx:=PROCNAME(i)
IF !EMPTY(sx)
res += sx
IF lNeedLines
res += "("+NTRIM(PROCLINE(i))+")"
ENDIF
IF i < nTo
res += cDefSep
ENDIF
ENDIF
NEXT i
RETURN res
* ---------------------------------------- *

Удобно в некоторых случаях делать например так: ProcStack(,,TRUE,CRLF) или просто ProcStack()

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


Пост N: 126
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 11.11.13 13:20. Заголовок: Sergy пишет: Один ю..


Sergy пишет:

 цитата:
Один юзер хочет прямо сейчас найти "Моск", юзер на соседнем компе - "Якут" в тоже самое время.
Через минуту первому потребовалось "Санкт-П", а другому - "Казань". Через пару минут дальше - "Иваново". Третий юзер в тоже самое время начал искать "Владивосток".

Перестраивать индекс каждый раз?


Нет. Меняется временный индекс да и тот у каждого юзера свой ( на локальной машине )

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




Пост N: 3076
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 11.11.13 15:47. Заголовок: ММК пишет: Нет. Мен..


ММК пишет:

 цитата:
Нет. Меняется временный индекс да и тот у каждого юзера свой ( на локальной машине )


Ага. Я это имел в виду.

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




Пост N: 3708
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 11.11.13 16:16. Заголовок: Andrey Так хотел пр..


Andrey
Так хотел пример (который я дал) и ни чего не ответил в плане BM фильтра.........или не юзал ?

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




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


Dima пишет:

 цитата:
или не юзал ?


Спасибо БОЛЬШОЕ. Я его делаю, но там всего много навороченного, так что делаю отдельную версию.

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





Пост N: 377
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 17.11.13 19:04. Заголовок: ММК пишет: Нет. Мен..


ММК пишет:

 цитата:
Нет. Меняется временный индекс да и тот у каждого юзера свой ( на локальной машине )


Ну ведь для того, чтобы перестроить индекс (даже локально) - нужно перечитать все записи, хранящиеся на сервере (удаленно).


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




Пост N: 3094
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 17.11.13 20:01. Заголовок: Sergy пишет: Ну вед..


Sergy пишет:

 цитата:
Ну ведь для того, чтобы перестроить индекс (даже локально) - нужно перечитать все записи, хранящиеся на сервере (удаленно).


Поверь, это происходить ОЧЕНЬ быстро.
База примерно 50.000 записей, поиск по различным полям базы, включая текстовые поля и мемо-поля. Индексирование происходит за 40-60 сек. сек.
Если есть уже открытый индекс по которому нужно выбрать значение, т.е. допустим ФИО и дату (любую) и еще чего нибудь, то 10-20 сек.
Эту технологию сделал еще в 1997 г. на Клипере 5.3 и до сих пор использую.
Хотя надо бы переходить на LetoDB....


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





Пост N: 68
Зарегистрирован: 17.10.05
ссылка на сообщение  Отправлено: 18.11.13 13:33. Заголовок: Andrey пишет: Ну ве..


Andrey пишет:

 цитата:
Ну ведь для того, чтобы перестроить индекс (даже локально) - нужно перечитать все записи, хранящиеся на сервере (удаленно).


когда-то, когда Clipper еще помещался на 720к дискету, существовала такая приблуда, которая называлась SUBINDEX. Это была и автономная программка, и библиотека для S'87 и 5.01..
по памяти где-то так:
subindex(исходный-ntx,результирующий-ntx,маска-отбора)
т.е. строился индекс на основании другого индекса, даже не обращаясь к записям таблицы. маска например "ИВАНОВ*"
я просто для иллюстрации подхода ;-)

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


Пост N: 718
Зарегистрирован: 06.07.06
ссылка на сообщение  Отправлено: 18.11.13 14:43. Заголовок: LYSK пишет: существ..


LYSK пишет:

 цитата:
существовала такая приблуда, которая называлась SUBINDEX.


Это была одна из фичей Six3. В Harbour это тоже есть, сам, правда, не пробовал.

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




Пост N: 3040
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.11.13 15:07. Заголовок: Andrey пишет: Повер..


Andrey пишет:

 цитата:
Поверь, это происходит ОЧЕНЬ быстро.
База примерно 50.000 записей, поиск по различным полям базы, включая текстовые поля и мемо-поля. Индексирование происходит за 40-60 сек. сек.
Если есть уже открытый индекс по которому нужно выбрать значение, т.е. допустим ФИО и дату (любую) и еще чего нибудь, то 10-20 сек.
Эту технологию сделал еще в 1997 г. на Клипере 5.3 и до сих пор использую.



Использование индекса с условием for - это некрасивое решение, поскольку для поиска формируется ненужный разовый индекс, при создании которого идет выборка всего файла.
Другое дело - индекс действительно строится очень быстро, даже быстрее цикла по всему файлу без индекса.
Причина этого - данные из файла считываются в режиме _SET_STRICTREAD, непосредственно из файла с использованием служебного буфера.

Сразу же возникает мысль использовать такой же режим для поиска.

Вот эта маленькая функция: http://zalil.ru/34818847
Использование функции:
dbEvalDirect(bDo, bFilter)
Смысл параметров такой же, как и в dbEval()

Пример:

aRecs := {}
dbEvalDirect({|| AADD(aRecs, RecNo())}, bFilter)

Функция не учитывает установки set filter, scope, и прочее, считывает полностью весь файл, от первой до последней записи.
Работает еще быстрее, чем построение индекса с for, так как не создается ненужный индекс.
Использовать ее можно только для rdd DBF*: DBFNTX,DBFCDX и их производных (BM*)
Какие есть еще подводные камни - надо подумать, так как я эту функцию сделал спонтанно, как только появилась такая идея.


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




Пост N: 3720
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.11.13 15:20. Заголовок: Pasha пишет: dbEval..


Pasha пишет:

 цитата:
dbEvalDirect(bDo, bFilter)


Вариант конечно когда нет подходящего индекса а если есть то быстрее будет конечно через dborderinfo(DBOI_SKIPREGEX,,,cRegex)
сделать выборку.

PS
Примерчик выше

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





Пост N: 378
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 18.11.13 15:27. Заголовок: Pasha пишет: Исполь..


Pasha пишет:

 цитата:
Использование индекса с условием for - это некрасивое решение, поскольку для поиска формируется ненужный разовый индекс, при создании которого идет выборка всего файла.


Согласен с этим. Поскольку при таком подходе из всех возможных вариантов будет использован наиболее медленный, с перечитыванием всего файла с начала и до конца. Банальный SET FILTER так будет себя вести только в том случае, если удовлетворяющих записей меньше, чем строк DBEDIT() на экране. Во всех остальных случаях он будет быстрее.


 цитата:
Вот эта маленькая функция: http://zalil.ru/34818847
Использование функции:
dbEvalDirect(bDo, bFilter)
Смысл параметров такой же, как и в dbEval()


Спасибо, изучу.

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


Пост N: 128
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 18.11.13 15:30. Заголовок: LYSK пишет: Ну ведь..


LYSK пишет:

 цитата:
Ну ведь для того, чтобы перестроить индекс (даже локально) - нужно перечитать все записи, хранящиеся на сервере (удаленно).


LYSK пишет:

 цитата:
строился индекс на основании другого индекса, даже не обращаясь к записям таблицы. маска например "ИВАНОВ*"
я просто для иллюстрации подхода ;-)


Т.е. необходимо и достаточно наличие хотя бы одного индекса, на основе которого и происходят все последующие выборки.
Вот, например , сырье .Индекс по наименованию. Выбираем ( правой кл. мыши ) поле "остаток на нач.дня" равное нулю ( или вводим любое нужное значение )


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




Пост N: 3041
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.11.13 15:31. Заголовок: Sergy пишет: Спас..


Sergy пишет:

 цитата:


Спасибо, изучу.



Эта функция не для прерывания фильтра, я просто не стал создавать новую тему, раз уж вопрос с условной индексацией всплыл здесь опять.
Назначение функции - быстрый поиск по всему файлу с произвольным условием. Можно еще добавить параметр - прерывание поиска при первом успешном попадании.

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


Пост N: 129
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 18.11.13 15:35. Заголовок: В этой выборке меня ..


В этой выборке меня интересует сырье , для которого были поступления- соответственно другое поле и другое значение ( выборка в выборке )

Это можно делать в любой последовательности для любого кол-вы полей


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




Пост N: 3042
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 18.11.13 17:05. Заголовок: Pasha пишет: Какие ..


Pasha пишет:

 цитата:
Какие есть еще подводные камни - надо подумать,



Я вижу только один такой: если в процессе чтения файла через dbEvalDirect другой пользователь добавит запись, то dbEvalDirect эту запись не увидит, так как RecCount определяется перед началом выборки.
Но это и есть причина такой высокой скорости: при обычной выборке каждый раз обновляется RecCount, а для этого делается fseek на конец файла, что заметно замедляет работу.
Но и индексация происходит точно так же: если во время индексации другой пользователь добавит новую запись, эта запись не попадет в индекс.

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




Пост N: 3097
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 18.11.13 17:57. Заголовок: Какое решение самое ..


Какое решение самое лучшее для БЫСТРОГО поиска по различным полям без открытых индексов ?
Решение Pasha или
Dima пишет:

 цитата:
Вариант конечно когда нет подходящего индекса а если есть то быстрее будет конечно через dborderinfo(DBOI_SKIPREGEX,,,cRegex)



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




Пост N: 3723
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.11.13 18:05. Заголовок: Andrey Берешь базу ..


Andrey
Берешь базу на пару-тройку лимонов записей и делаешь 2 теста и смотришь что быстрее.

PS
Ответь мне на ЛС

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




Пост N: 3098
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 18.11.13 18:13. Заголовок: Dima пишет: Берешь ..


Dima пишет:

 цитата:
Берешь базу на пару-тройку лимонов записей и делаешь 2 теста и смотришь что быстрее.


На ЛС ответил.
Помоги сделать эти тесты ? Ну очень интересно... Всем тоже узнать хочется !!!
А я что нибудь другое сваяю для тебя ?

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




Пост N: 3724
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 18.11.13 18:18. Заголовок: Andrey Давай мне ба..


Andrey
Давай мне базу да побольше и условия фильтрации (для начала хватит по одному-двум полям)

или

Опиши структуру базы , чем заполнять и что будем искать.

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




Пост N: 3099
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 18.11.13 19:26. Заголовок: Хорошо, делаю...


Хорошо, делаю.

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


Пост N: 130
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 19.11.13 11:06. Заголовок: Andrey пишет: Какое..


Andrey пишет:

 цитата:
Какое решение самое лучшее для БЫСТРОГО поиска по различным полям без открытых индексов ?
Решение Pasha или
Dima пишет:


Если воообще без индексов , то Locate :) Но и тут надо уточнить- "дикий" поиск или точный. Будет ли продолжение ( добавление следующих условий ) или "начни с начала" :)))
Каждая задача имеет свое конкретное решение и сравнивать их нет смысла

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




Пост N: 3043
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.11.13 10:58. Заголовок: Andrey пишет: Хорош..


Andrey пишет:

 цитата:
Хорошо, делаю.



Тест
Обьект тестирования - doma.dbf из КЛАДР, размер - 203М, более 2-х млн. записей
Выражение поиска: "229"$Name
Количество попаданий - 2310
Файл открыт через DBFCDX с индексом в режиме shared
Тест1: поиск без управляющего индекса - 5.9 сек
Тест2: поиск c управляющим индексом - 18.6 сек
Тест3: построение индекса с for - 0.83 сек
Тест4: поиск dbEvalDirect - 0.81 сек

Вывод (он и так напрашивался): - dbEvalDirect немного быстрее индексации с for
Понятно, что с файлами таких экстремальных размеров редко имеешь дело.
На файле размером 40M (~300 тыс.записей) время выполнения index ... for и dbEvalDirect примерно одинаково (просто погрешность выше, чем разница в скорости)
На небольшом файле размером 8М (~40 тыс.записей) index ... for выполняется за 0.05 сек, а dbEvalDirect - за 0.03 сек. (разница чувствуется)


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




Пост N: 3102
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.11.13 11:50. Заголовок: Pasha БОЛЬШОЕ спасиб..


Pasha БОЛЬШОЕ спасибо за тесты.
Я свою заготовку переслал Диме. У меня там замороченей тест получается... В смысле много полей ищется сразу в базе.

Можешь ли выложить свой исходник теста ?
Хочется посмотреть код профессионала.
Заранее спасибо.

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




Пост N: 3044
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.11.13 12:23. Заголовок: Такая большая пробле..


Такая большая проблема сделать простейший тест, что ли ?
Вот код:

Field TarCV, LS 
Field Otkomu, Date
Field Name

func main
Local bFor := {|| "229"$Name}
//Local bFor := {|| "Охрана"$Otkomu}
//Local bFor := {|| "229"$TarCV}
local cf := 'doma'
//local cf := 'carecs'
//local cf := 'tplus'

Local nSec, nk
Local bDo := {|| nk ++}

request dbfcdx

dbUseArea(.t., 'DBFCDX', cf,, .t.)
ordListAdd(cf)
dbSetOrder(0)
nk := 0
nSec := Seconds()
dbEval(bDo, bFor)
? 'DBFCDX-0', nk, Seconds() - nSec
close

dbUseArea(.t., 'DBFCDX', cf,, .t.)
ordListAdd(cf)
nk := 0
nSec := Seconds()
dbEval(bDo, bFor)
? 'DBFCDX-1', nk, Seconds() - nSec

go top
nk := 0
nSec := Seconds()
dbEvalDirect(bDo, bFor)
? 'DBFCDX-2', nk, Seconds() - nSec

nSec := Seconds()
index on Code tag (cf+'1') to (cf+'1') for "229"$Name
//index on Date tag (cf+'1') to (cf+'1') for "Охрана"$Otkomu
//index on LS tag (cf+'1') to (cf+'1') for "229"$TarCV
? 'Index for', ordKeyCount(), Seconds()-nSec

close

return nil



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




Пост N: 3046
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.11.13 14:22. Заголовок: Можно классифицирова..


Можно классифицировать скорость выборки на 3 уровня:

1. При монопольном доступе к файлу, во время индексации, и в только что написанной функции dbEvalDirect
Скорость максимальная, так как ресурсы расходуются только на чтение исходного файла, и больше ни на что.
При этом для монопольного доступа возможно чтение любого фрагмента файла с управляющим индексом или без него.
С индексом скорость будет немного хуже.
Для индексации и dbEvalDirect считывается весь файл.
Поскольку letodb открывает файлы монопольно, то на него не влияют факторы, описанные ниже.

2. Для файла, открытого в режиме shared без управляющего индекса. Скорость в несколько раз хуже за счет того,
что при чтении каждой записи обновляется reccount.

3. Для файла, открытого в режиме shared с управляющим индексом. Скорость еще в несколько раз хуже, чем для п.2
Причина этого, кроме момента, указанного в п.2 - блокировка индекса на чтение при чтении каждой записи. Этот момент можно резко улучшить, задав dbOrderInfo(DBOI_READLOCK,,, .t.) перед выборкой.
Еще причина - выборка записи по ключу в самом индексе, т.е. чтение индекса.


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




Пост N: 3103
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.11.13 14:23. Заголовок: А как отобразить ото..


А как отобразить отобранные записи в BROWSE() ?
Я сталкивался с такой задачей, т.е. есть в массиве номера записей (полученные из поиска) которые нужно отобразить на экране.
Как в таком случае поступают (с учетом работы в будущем не LetoDB) ?



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




Пост N: 3728
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.11.13 14:29. Заголовок: Andrey BM фильтр я ..


Andrey
BM фильтр (затем browse) я же пример приводил выше

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




Пост N: 3105
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.11.13 14:38. Заголовок: Dima пишет: BM филь..


Dima пишет:

 цитата:
BM фильтр (затем browse) я же пример приводил выше


А без BM фильтра ?
Я у себя давно делал поиск по подчиненной базе. Приходилось при поиске в доп.поле записывать 0, а при нахождении 1, а потом показывать записи с кодом=1 . Это не оптимально.
Вот и хочу понять как такие вещи делать ?

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




Пост N: 3729
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.11.13 14:44. Заголовок: Без BM будет не опти..


Без BM будет не оптимально. Как вариант складывать можно выбранные записи во временную базу
Или переделать Skipper что бы он ходил по массиву с номерами записей


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




Пост N: 3047
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.11.13 14:59. Заголовок: Andrey пишет: А как..


Andrey пишет:

 цитата:
А как отобразить отобранные записи в BROWSE() ?



Сделать источником данных для browse не р/о, а массив. В массив загонять те данные, которые надо выдать, плюс номер записи. После выбора нужной строки массива делать dbGoto() по номеру выбранной записи из строки массива.

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




Пост N: 3109
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 21.11.13 21:53. Заголовок: Pasha пишет: Сделат..


Pasha пишет:

 цитата:
Сделать источником данных для browse не р/о, а массив. В массив загонять те данные, которые надо выдать, плюс номер записи. После выбора нужной строки массива делать dbGoto() по номеру выбранной записи из строки массива.


А по другому никак ? Сложновато получается... Или мне кажется только ?
Минимальный код для такого BROWSE() привести можете ?

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




Пост N: 3730
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 21.11.13 22:01. Заголовок: Andrey Похоже читае..


Andrey
Похоже читаешь сообщения но ни чего не тестишь отсюда и не понятки.
Сделай простейший пример с BM фильтром и все станет ясно.
Что касается Browse то он у каждого свой под свои задачи и в любом из них
есть Skipper или аналог вот его и нужно переделать если что.

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




Пост N: 3110
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 21.11.13 22:39. Заголовок: Dima пишет: Похоже ..


Dima пишет:

 цитата:
Похоже читаешь сообщения но ни чего не тестишь отсюда и не понятки.


Делаю. На этой неделе выложу.

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





Пост N: 379
Зарегистрирован: 08.07.06
ссылка на сообщение  Отправлено: 22.11.13 21:09. Заголовок: Andrey пишет: А как..


Andrey пишет:

 цитата:
А как отобразить отобранные записи в BROWSE() ?
Я сталкивался с такой задачей, т.е. есть в массиве номера записей (полученные из поиска) которые нужно отобразить на экране.
Как в таком случае поступают (с учетом работы в будущем не LetoDB) ?



Со времен Clipper, когда нужных записей в большой таблице мало - выяснил, что гораздо эффективнее их считать в массив, а потом только их и показывать. Примерно так:
 
aRx:={}
GO TOP
DO WHILE !EOF()
IF ....
AADD(aRx,RECNO())
ENDIF
SKIP
ENDDO
DbViewByArray(a+1,1,MAXROW()-5,MAXCOL()-1,aValues[1],"CallBackFunc",aRx,@nPos)


где:
Скрытый текст



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




Пост N: 3111
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 23.11.13 19:33. Заголовок: Dima пишет: Похоже ..


Dima пишет:

 цитата:
Похоже читаешь сообщения но ни чего не тестишь отсюда и не понятки.



Сделал тест на базу 101тыс. записей. Реально рабочий пример.
В базе 12 полей FAM1-FAM12, NAME1-NAME12, OTCH1-OTCH12
Делать поиск сразу по этим полям сложно.
SET FILTER и LOCATE успешно ищет. Правда показ в BROWSE() по SET FILTER - тормоза !
Время поиска просто очень мало 1сек. Может у меня комп такой... На сети пока не тестил, на след.неделе сделаю.
Поиск по SEEK не стал реализовывать. Что-то очень сложный алгоритм получается...
dbEvalDirect() - не работает, слишком большое условие поиска (больше 900 символов).
Павел, если можно сделать большую строку поиска, то очень хорошо, если нет, то не страшно.
Dima пишет:

 цитата:
пример с BM фильтром


Жду от Димы.
Вообще кто, что можете порекомендовать, пишите.
Я не смотря на долгую работу с Клипером, всех тонкостей не знаю.
Сам проект на хХарборе 1.2.3 http://files.mail.ru/5D8A880F51054F7BBB3A279FB1E279EA

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




Пост 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 
ПрофильЦитата Ответить
постоянный участник




Пост N: 3120
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 25.11.13 21:52. Заголовок: Pasha пишет: Не буд..


Pasha пишет:

 цитата:
Не буду даже пытаться объяснить, что к чему, просто покажу, как надо сделать:


Спасибо БОЛЬШОЕ !
Как увидел, так сразу понял, раньше так делал. Просто уже глаза замылились....

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




Пост N: 3737
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 25.11.13 22:02. Заголовок: Andrey пишет: Прост..


Оффтоп:
Andrey пишет:

 цитата:
Просто уже глаза замылились


Глазам отдых нужен !


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




Пост N: 3121
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 26.11.13 11:44. Заголовок: dbEvalDirect() - зар..


dbEvalDirect() - заработал. Но Browse() ломается при показе после него и программ вылетает.
Массив создается нормально.

// Создание блока кода из выражения поиска
bFilter := &("{||" + cFilterTo + "}")
SELECT DOGOVOR
dbEvalDirect(bDo, bFilter)
BROWSE(1,0,MAXROW(),MAXCOL())



Как починить dbEvalDirect() или после него нельзя вызывать browse() ?
C dbeval() таких проблем нет.

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




Пост N: 265
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 26.11.13 13:40. Заголовок: Pasha dbEvalDirect()..


Pasha
dbEvalDirect() портит что-то ...
prg: Скрытый текст

hb_out.log:Скрытый текст

мой log, тест работы:Скрытый текст


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




Пост N: 3052
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 27.11.13 18:54. Заголовок: SergKis пишет: Pash..


SergKis пишет:

 цитата:
Pasha
dbEvalDirect() портит что-то ...



Поправил, переименовал функцию в dbfEval, добавил поддержку всех параметров, как в dbEval, сборку под xharbour:

http://files.mail.ru/A324711CF8A94781808E50C7BEB48B30

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




Пост N: 267
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 27.11.13 20:43. Заголовок: Pasha prg: a := {} d..


Pasha
prg:Скрытый текст

без Browse не снимается с Browse валится hb_out.log:
Скрытый текст


содержимое hb_out.log получено за один запуск exe.
вариант со стандартным dbEval работает.

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




Пост N: 268
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 27.11.13 20:50. Заголовок: Pasha это hb 3.2 bcc..


Pasha
это hb 3.2 bcc.
под MSVC и hb 2.0 без browse валится на USE закрытия. hb_out.log:Скрытый текст



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




Пост N: 3126
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 27.11.13 21:17. Заголовок: Pasha Не собирается..


Pasha
Не собирается под
xHarbour 1.2.3 Intl. (SimpLex) (Build 20130903)
Скрытый текст


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


Пост N: 131
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 28.11.13 10:53. Заголовок: Andrey пишет: Не со..


Andrey пишет:

 цитата:
Не собирается под


Пока возникли небольшие технические трудности я вас немножко развлеку. Необходимость в функции поиска возникает регулярно.
И регулярно появляются разные варианты (но в Харбор , как стандартную функцию их почему то не включают :) )
Вот один из таких :))

http://files.mail.ru/4B45968E44E6429AB810802AB86AE7DF

База shared , без индекса. Записей чуть больше трех с половиной лимонов. При поиске используются стандартные управляющие
символы "?" и "*" . Анализ кодировки ( дос или win) и формирование массива с номерами найденных записей.
Формат функции : поле, шаблон поиска, кодировка.

#include "FiveWin.ch"
Function Main

Local nTime,n:=0
Local popa:={}, vr

RDDSetDefault('DBFCDX')
Use dr new shared

nTime := Seconds()
while (vr:=FLocate('TYJ','D?d*','D'))<>-1
N:=n+1
aadd(popa,vr)
enddo
MsgInfo( Seconds() - nTime )
for vr=1 to len(popa)
MsgInfo( popa[vr] )
next
Return NIL

Скорость ,естественно , зависит от машины. Есть небольшая погрешность - память очищается не "до" , а "после " поэтому запустите
примерчик два-три раза.... На моей машине это приблизительно 0.7 секунды



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




Пост N: 269
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 28.11.13 11:35. Заголовок: MMK пишет:На моей ма..


MMK пишет:
 цитата:
На моей машине это приблизительно 0.7 секунды


у меня ~ 1.37. но в данном примере 4 поля и длина записи 40, в моем 92 и 912. Функция dbfEval работает в 4 раза быстрее стабильно:
 
Do while: 2.2470 ARRAY[51218] 206904
DbEval : 2.2460 ARRAY[51218] 206904
DbfEval : 0.5140 ARRAY[51218] 206903


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




Пост N: 3740
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 28.11.13 11:39. Заголовок: ММК пишет: FLocate ..


ММК пишет:

 цитата:
FLocate


Что за черный ящик ?

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


Пост N: 132
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 28.11.13 14:56. Заголовок: SergKis пишет: но ..


SergKis пишет:

 цитата:
но в данном примере 4 поля и длина записи 40, в моем 92 и 912


Ну это понятно, понятно.... А не затруднит Вас сделать поиск по моей базке и сформировать массив?
Шаблон D?d* . Т.е. с учетом ? и * . Для чистоты эксперемента :))))

Dima пишет:

 цитата:
Что за черный ящик ?



Да старые архивы перебирал :) Нашел Fast Locate




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




Пост N: 3741
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 28.11.13 14:58. Заголовок: ММК пишет: Нашел Fa..


ММК пишет:

 цитата:
Нашел Fast Locate


Исходничек тоже есть ? :)

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




Пост N: 270
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 28.11.13 18:04. Заголовок: MMK пишет: А не затр..


MMK пишет:
 цитата:
А не затруднит ...


Сделал:
маску превратил в: upper(left(TYJ,1)+subs(TYJ,3,1)) == 'DD'
 
Do while: 35.1160 ARRAY[5] 3506491
DbEval : 35.7870 ARRAY[5] 3506491
DbfEval : 7.3320 ARRAY[5] 3506490

Результат FastLocate впечатляет !

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




Пост N: 3054
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 28.11.13 19:20. Заголовок: SergKis пишет: без ..


SergKis пишет:

 цитата:
без Browse не снимается с Browse валится hb_out.log:



Я пока в затруднении. Дело в том, что я таких ошибок не получаю, никакого последействия нет. Вот прицепил эту функцию к своему dbedit, тоже все работает.
Да и кода в dbfEval с гулькин нос, непонятно, откуда взяться ошибке.

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




Пост N: 3127
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 28.11.13 19:30. Заголовок: Pasha Не собирается ..


Pasha
Не собирается под
xHarbour 1.2.3 Intl. (SimpLex) (Build 20130903)

Скрытый текст


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




Пост N: 271
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 28.11.13 20:59. Заголовок: Pasha собрал как ест..


Pasha
собрал как есть: http://gfile.ru/a2yK5
browse перестал слетать и пару раз даже без снятия отработал.

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


Пост N: 133
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 29.11.13 10:31. Заголовок: SergKis пишет: Do ..


SergKis пишет:

 цитата:
Do while: 35.1160 ARRAY[5] 3506491
DbEval : 35.7870 ARRAY[5] 3506491
DbfEval : 7.3320 ARRAY[5] 3506490


Результат FastLocate впечатляет !



Спасибо , что уделили внимание !

Pasha пишет:

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



Если у Вас есть желание и время я пришлю Вам исходник. Может из двух вариантов получится что хорошее для народа :))
Dima пишет:

 цитата:
Исходничек тоже есть ? :)


Вот ,собственно говоря , ответ :)))


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




Пост N: 3742
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 29.11.13 14:25. Заголовок: ММК пишет: Если у В..


ММК пишет:

 цитата:
Если у Вас есть желание и время я пришлю Вам исходник. Может из двух вариантов получится что хорошее для народа :))


Ждем Пашу !

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




Пост N: 3055
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 29.11.13 14:42. Заголовок: Да я уже со всем раз..


Да я уже со всем разобрался, вечером скину.
Должен сказать, что в letodb выборка по установленному фильтру по скорости сопоставима с dbfEval, (хотя чуть медленнее)
Но так и должно быть, поскольку letodb работает в монопольном режиме.
А насчет fast locate - если его скорость сопоставима или лучше, чем в dbfEval, есть смысл на него глянуть.

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


Пост N: 134
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 29.11.13 16:50. Заголовок: Pasha пишет: есть ..


Pasha пишет:

 цитата:
есть смысл на него глянуть.


отправил

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




Пост N: 3056
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 29.11.13 20:32. Заголовок: Ссылка на исправленн..


Ссылка на исправленный dbfEval:
http://files.mail.ru/10FD94F47C824895BC5C8CB1913BC973

По поводу dbFLocate. Также используются файловые операции. Не тестировал, только смотрел сырцы. Поиск выполняется по одному полю, независимо от его типа, поле считывается как строка, поиск выполняется по hb_strMatchWild.
Если нужен поиск по одному полю, то dbFLocate будет немного быстрее, чем dbfEval. Но dbfEval более универсален, так как в качестве выражения для поиска можно использовать произвольный блок кода.

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




Пост N: 3131
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 29.11.13 22:50. Заголовок: Pasha пишет: Ссылка..


Pasha пишет:

 цитата:
Ссылка на исправленный dbfEval:


Не собирается опять проект на хХарборе с этим файлом.
Вот такая ошибка:
xHarbour 1.2.3 Intl. (SimpLex) (Build 20130903)
Скрытый текст


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


Пост N: 135
Зарегистрирован: 29.05.10
ссылка на сообщение  Отправлено: 30.11.13 10:10. Заголовок: Pasha пишет: Если н..


Pasha пишет:

 цитата:
Если нужен поиск


Понимаете , Паша , идея была в том что бы объеденить эти функции т.к. каждая из них имеет свои достоинства. Скажем по параметру запускать один из вариантов.
Поиск по одному полю гораздо быстрее и наличие MatchWild очень вожно. dbfEval хорош для общего поиска.
Но поиск это поиск , а фильтр это фильтр :)) Для себя я это представляю ( и делаю ) , как три разные задачи;
Поиск. Фильтр, когда он ставится один раз и под заранее оговоренный отчет. Вложенные фильтры-когда пользователь
ставит каждый последующий в зависимости от результата предыдущего. Т.е. "творчески" работает с базой :)
И варианты могут быть любые, соответственно не очень удобно создавать на все поля индексы ( особенно , если этих полей 100-150 ) и (или)
писать обработку массивов для такой ситуации.
Для вложенных фильтров использую не index.. for , а
index on ... to tsmy_idx for !deleted() CUSTOM ADDITIVE
Он создается на локальной машине и дальнейшая работа идет не с базой , а с индексом. И мы его не перестраивааем , а корректируем. Например передается вид операции ( больше, меньше и т.д. ) и необходимое значение.
Поэтому любой пользователь может ставить свой филтр вне зависимости от других.
А дальще -
....
myblock:=&('{||iif('+bloo+alltrim(znak)+'"'+alltrim(wot)+'",ORDKEYADD("TSMY_IDX","tsmy_idx.cdx",'+mykey+'),)}')
...
dbeval(myblock)
или , соответственно -
myblock:=&('{||iif('+bloo+alltrim(znak)+'"'+alltrim(wot)+'",,ORDKEYDEL("TSMY_IDX"))}')
Можно использовать и "вилд" фильтр

А теперь просто "рефрешь" бровса. По ощущениям "прорисовка экран" идет медленнее , чем работа фильтра.
Новое условие на этот филтр - новая корректировка dbeval(myblock)





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




Пост N: 3745
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 30.11.13 16:03. Заголовок: Andrey пишет: Error..


Andrey пишет:

 цитата:
Error E2451 DBFEVAL.PRG 49: Undefined symbol 'hDataFile' in function HB_FUN_DBFEVAL
Error E2451 DBFEVAL.PRG 53: Undefined symbol 'hDataFile' in function HB_FUN_DBFEVAL


Не уверен но возможно вместо hDataFile нужно написать pDataFile

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




Пост N: 3096
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 19.12.13 09:50. Заголовок: Наконец-то разобралс..


Наконец-то разобрался со сборкой для xHarbour SVN
Оказывается, там размерность типов данных ULONG и HB_ULONG разная

Скачать исходник dbfeval:
http://zalil.ru/34858902

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




Пост N: 3180
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 19.12.13 12:16. Заголовок: Спасибо БОЛЬШОЕ Pash..


Спасибо БОЛЬШОЕ Pasha !
Компилируется нормально.

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




Пост N: 3181
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 19.12.13 12:30. Заголовок: А почему в dbfEval()..


А почему в dbfEval() если есть условие ".AND.!DELETED()" - все равно показывает удаленные записи ?

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




Пост N: 3100
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.12.13 14:04. Заголовок: Проверил - вроде как..


Проверил - вроде как с этим флагом все нормально, он учитывается.

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




Пост N: 3184
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.12.13 16:49. Заголовок: Pasha пишет: Провер..


Pasha пишет:

 цитата:
Проверил - вроде как с этим флагом все нормально, он учитывается.



Вот тестовый пример на хХарборе.
http://files.mail.ru/32A93B73CC8F40BE900F5E889C5E7711
При первом запуске программы создаются базы в папке проекта DBF и файл пути к базе DBF_search.path
Базы можно перекинуть на сервер и поменяв путь в DBF_search.path - тестировать скорость по сети.
Хотя реальные тесты показывают совсем другое время.
При работе нескольких программ в сети скорость LOCATE с 3 секунд может увеличиться до 3х минут.
SET FILTER тоже не подарок...

Условие ".AND.!DELETED()" - не учитывается в SET FILTER, LOCATE, dbfEval()
Может строка поиска большая ?


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




Пост N: 3777
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.12.13 17:29. Заголовок: Andrey Subsystem C..


Andrey
 
Subsystem Call ....: DBFCDX
System Code .......: 1004
Default Status ....: .T.
Description .......: Ошибка создания
Operation .........:
Arguments .........:
Involved File .....: C:\1\555\dd\6\1\DBF\TestDogovor.dbf
Dos Error Code ....: 3

Trace Through:
----------------
DBCREATE : 0 in Module:
CREATE_TEST_DBF : 235 in Module: OPENDBFDIC.PRG
MYOPENDBF : 18 in Module: OPENDBFDIC.PRG
MAIN : 31 in Module: DBF_SEARCH.PRG



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




Пост N: 3186
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.12.13 18:43. Заголовок: Dima пишет: C:\..


Dima пишет:

 цитата:
C:\1\555\dd\6\1\DBF\TestDogovor.dbf


Сделай путь покороче, типа D:\DBF-Search

Точно вылетает... Буду смотреть...

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




Пост N: 3779
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 20.12.13 18:46. Заголовок: Andrey я вообще рук..


Andrey
я вообще руками ни чего не делал и просто распаковал в эту папку и запустил EXE
Могу понять что могло заглючить если бы папка была кириллицей названа.

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




Пост N: 3102
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.12.13 19:57. Заголовок: Andrey пишет: Услов..


Andrey пишет:

 цитата:
Условие ".AND.!DELETED()" - не учитывается в SET FILTER, LOCATE, dbfEval()



Все упомянутые средства работают правильно, это неправильное условие поиска.
Сколько будет дважды два .t. .or. .t. .and. .f. ?
Подсказка: правильно будет (.t. .or. .t.) .and. .f.

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




Пост N: 3103
Зарегистрирован: 23.05.05
ссылка на сообщение  Отправлено: 20.12.13 19:58. Заголовок: Dima пишет: я вообщ..


Dima пишет:

 цитата:
я вообще руками ни чего не делал и просто распаковал в эту папку и запустил EXE



там ручками надо создать папку dbf

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




Пост N: 3188
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 21.12.13 13:42. Заголовок: Pasha пишет: Подска..


Pasha пишет:

 цитата:
Подсказка: правильно будет (.t. .or. .t.) .and. .f.



Спасибо БОЛЬШОЕ !
Вечно торопливость мешает правильно делать...
А когда сделаешь, уже считаешь что всё правильно !
Исправленный пример - http://files.mail.ru/97F319C31C944A199D7AA97DA0136E7A

SET FILTER - при первом запуске хорошо тормозит, 15 сек. поиска на локальной машине....
А что будет с ним на сервере, я даже не представляю.

Dima - модуль FindBMDBFCDX.prg тебя ждет !

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




Пост N: 3780
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 21.12.13 14:42. Заголовок: Andrey пишет: Вечно..


Andrey пишет:

 цитата:
Вечно торопливость мешает правильно делать...


Это точно

 
-------------------- Internal Error Handling Information ---------------------

Subsystem Call ....: DBFCDX
System Code .......: 1004
Default Status ....: .T.
Description .......: Ошибка создания
Operation .........:
Arguments .........:
Involved File .....: D:\DBF-Search\DBF\TestDogovor.dbf
Dos Error Code ....: 3

Trace Through:
----------------
DBCREATE : 0 in Module:
CREATE_TEST_DBF : 235 in Module: OPENDBFDIC.PRG
MYOPENDBF : 18 in Module: OPENDBFDIC.PRG
MAIN : 31 in Module: DBF_SEARCH.PRG




Andrey пишет:

 цитата:
Dima - модуль FindBMDBFCDX.prg тебя ждет !


А чего ?
Мало примера что я дал ?
Принцип тот же , выбираем в массив удовлетворяющие записи.
Но поиск происходит по индексам (при чем по каждому такому полю
нужно иметь индекс).

ЗЫ
Сел бы и разобрался без спешки и вопросов бы не было , впрочем их и не было
даже после того как я показал самодостаточный пример и полагал что все ясно.
В Xharbour в тестах вроде же есть пример skipeval.prg я его просто чуть модифицировал.


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




Пост N: 3189
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 21.12.13 18:54. Заголовок: Dima пишет: Descrip..


Dima пишет:

 цитата:
Description .......: Ошибка создания
Operation .........:
Arguments .........:
Involved File .....: D:\DBF-Search\DBF\TestDogovor.dbf
Dos Error Code ....: 3



А точно пробовал последний пример - DBF-Search2.7z ?
У меня теперь в любой папке создает базу...
Пробовал так D:\TEMP\1\TEST\DBF
Не забыть удалить файл dbf_search.path если папки переименовал.

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




Пост N: 3781
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 21.12.13 19:26. Заголовок: Andrey Да я сделал ..


Andrey
Да я сделал как в прошлый раз распаковал архив в отдельную папку и запустил EXE
и выпал на эту ошибку. Искать ошибку лень да и Xharbour у меня нет что бы пересобрать.


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




Пост N: 3190
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 21.12.13 20:01. Заголовок: Dima пишет: Да я сд..


Dima пишет:

 цитата:
Да я сделал как в прошлый раз распаковал архив в отдельную папку и запустил EXE



Удали файл dbf_search.path, я его случайно в архив поместил.

Andrey пишет:

 цитата:
При первом запуске программы создаются базы в папке проекта DBF и файл пути к базе DBF_search.path
Базы можно перекинуть на сервер и поменяв путь в DBF_search.path - тестировать скорость по сети.



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

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