Коллекции, выборка

Тема в разделе "Lotus - Программирование", создана пользователем Gor, 26 май 2009.

  1. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    Всем дорого времени суток!

    Подскажите как возможно реализовать следующее, чтобы быстрее работало, что то ничё в голову не лезет((


    Есть документы, их много.

    В каждом поля Статус, Дата, ID ну и ещё куча разных полей.

    Необходимо собрать коллекцию, именно коллекцию (а не массив с юнидами и значениями) по принципу:

    Статус = Completed, Дата = Самая последняя к Today относительно UNID.
    Т.е. Если UNID совпадает, то в коллекции должен быть тот у которого Дата самая близкая к Today.

    Я реализовал это с помощью двух коллекций...
    т.е определяем оодну, берём каждый документ в этой коллекции, определяем другую по ID и последней Дате, если в ней Count > 0 (документы свежее) -делаем deleteDocument из 1-й коллекции, берём следующий... итд итп

    Работает жутко долго((
    Как по другому возможно реализовать?
     
  2. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Имхо, быстрее всего будет сделать через папку. Т.е. после изменения документа(статуса, даты или ID) проверять условие и добавлять(или удалять) в папку. А получить коллекцию будет несложно.

    Существующие документы нужно обработать агентом.
     
  3. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    Код (Text):
    Имхо, быстрее всего будет сделать через папку. Т.е. после изменения документа(статуса, даты или ID) проверять условие и добавлять(или удалять) в папку. А получить коллекцию будет несложно.

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

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Ну менять их и не надо. Агент всего лишь заполнит папку.
     
  5. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    Для Medevic:

    Вот эту фразу чего то не совсем понял... После какого изменения документа??? документы же не изменяются, они лежат себе в баез и лежат...
    можно чуть подробнее?Или на примере каком нибудь не большом? С папками почему то никогда не работал...
     
  6. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Документы же можно менять? Статус "Completed" установить или Дату изменить. Значит, после изменения документ уже может попасть(или наоборот выпасть) в твою коллекцию? Поэтому в PostSave надо сделать проверку условия и при необходимости изменить содержимое папки.
     
  7. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Gor
    Можешь выложить код перебора коллекций (как сами циклы организованы)?
    Может там что-нить не так (Nth например)?
     
  8. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    И много документов - это сколько? :)
     
  9. K-Fire

    K-Fire Гость

    Как возможный вариант:

    Делаем вьюшку, формула отбора Статус = Completed.
    Первый столбец - категория по UNID. Второй столбец Дата, сортирована по убыванию.

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

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


    Или еще 1 вариант. Все тоже самое, но имеем 2 вьюшки, в первой формула отбора больше текущей даты, сортировка по возрастанию, во второй - меньше текущей даты, сортировка по убыванию.
    Т.е. для каждого UNID нам надо будет взять первый документ в категории из каждой вью, и их уже сравнить.
     
  10. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    to Omh:
    Код (Text):
        Set coll = db.Search({Form = "MotivatedJudgementForm" & (Status= "Completed")},Nothing,0)

    Set doc = coll.GetFirstDocument
    While Not Doc Is Nothing
    Set coll1 = db.Search({Form = "Form" & (Status= "Completed")&MJ_GRID="}+doc.MJ_GRID(0)+{"&CompletedDate => [}+Cstr(doc.CompletedDate(0))+{]},Nothing,0)
    Set doc1 = coll.GetNextDocument(doc)

    If coll1.Count>1 Then Call coll.DeleteDocument(doc)

    Set doc = doc1
    Wend
    to Medevic:

    5000
     
  11. K-Fire

    K-Fire Гость

    Елы палы, db.Search то зачем? Вьюшку надо использовать, вьюшку!
     
  12. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Ну, конечно, 5000 сёрчей в цикле не лучшая идея.

    Ну первоначальный вариант у меня такой:
    1. собираем coll по формуле {Form = "MotivatedJudgementForm" & (Status= "Completed")}
    2. собираем coll1 по формуле {Form = "Form" & (Status= "Completed")}
    3. преобразуем coll1 в list вида ListName(MJ_GRID_VALUE) = CompletedDate
    4. вместо сёрча в цикле обрабатываем list

    Пока писал, придумал ещё так:
    1. собираем coll по формуле {Form = "MotivatedJudgementForm" & (Status= "Completed")}
    2. делаем view с selection formula = {Form = "Form" & (Status= "Completed")}
    3. в цикле вместо сёрча берём коллекцию из view по ключу (doc.MJ_GRID(0), True)
    4. перебираем эту маленькую коллекцию на проверку даты.

    Уверен, что можно ещё что-нить придумать.
    И скрипт будет резким, как понос.

    Во втором случае можно правильно отсортировать, как советовал K_Fire тремя постами выше, и тогда наверняка, вдруг запляшут облака, и кузнечик запиликает на скрипке!
     
  13. K-Fire

    K-Fire Гость

    Учитывая что документов всего 5000, ускорение будет раз в 100 :)
     
  14. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    Я может быть с датой не совсем правильно выразился. Даты необходимо сравнивать не с Today, а МЕЖДУ собой в документах по отношению к Today. Дата - это CompletedDay заявки. Т.е. нужны ТОЛЬКО последние одобренные заявки по ID.
     
  15. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    Завести список List As Variant.
    Ключем пусть будет UNID документа, а значением дата. Пройтись циклом по коллекции и перенести значения в список.
    Причем, проверять функцией Iselemet есть ли уже такой элемент в списке. Если есть, то проверить дату и внести(или не внести) новое значение.
    Потом опять в цикле пройтись по коллекции. Взять из списка элемент, соответствующий UNID'у и сравнить даты. Если не равны, то удаляем документ из коллекции.
     
  16. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Энивей надо сделать 2 view и не пускать сёрч пять тыщ раз.
     
  17. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    добавлю к вар. 2 п.4) (Omh):
    и по дате во вьюшке при желании сортировать можно и брать сразу самый последний.
     
  18. Medevic

    Medevic Что это ? :)
    Lotus team

    Регистрация:
    10 дек 2004
    Сообщения:
    3.346
    Симпатии:
    2
    5000 раз сделать GetAllDocumentsByKey - тормоза будут знатные. :)
     
  19. K-Fire

    K-Fire Гость

    Кстати, реально нам надо выполнить 5000 поисков. Допустим мы реализуем это как 5000 GetAllDocumentsByKey, и затем прохождение по найденной коллекции.

    Можно попробовать перед основным циклом загнать все документы по форме Form в List (ключ MJ_GRID), причем значением листа будет являтся другой лист, в котором ключ - дата. Уверен что это будет в десятки раз быстрее чем 5000 поисков.

    Это будет корректно работать если кол-во документов по форме Form не более какого-то числа, допустим 10 000, а может 100 000. Можно проверить экспериментально, с какого кол-ва 5000 поисков станут быстрее чем заполнение такого списка.
     
  20. Gor

    Gor Well-Known Member

    Регистрация:
    7 июн 2005
    Сообщения:
    517
    Симпатии:
    2
    В принципе сделал =) Работает значительно быстрее, хотя здесь может ещё чёнить подкроутить можна. Не люблю я вьюхи лишние плодить в базах для служебных целей... Сделал со списком и
    двойному проходу по коллекции

    Код (Text):
    Set coll = db.Search({Form = "MotivatedJudgementForm" & (Status= "Completed")},Nothing,0)

    Dim Listeg List As Variant

    i=0
    For i = 1 To coll.Count
    Set doc = coll.GetNthDocument(i)   
    If Iselement(Listeg(doc.MJ_GRID(0))) = True Then
    Forall id In Listeg
    If (Listtag(id) = doc.MJ_GRID(0)) And (Cdat(id) < Cdat(doc.CompletedDate(0))) Then
    'записываем в наш лист новую дату из дока и стираем элемент с текущим листтагом                                               
    Listeg(doc.MJ_GRID(0)) = doc.CompletedDate(0)                          
    Goto label                                         
    End If
    End Forall         
    Else
    Listeg(doc.MJ_GRID(0)) = doc.CompletedDate(0)          
    End If     
    label:
    Next   

    Set doc = coll.GetFirstDocument
    While Not doc Is Nothing       
    Set doc1 = coll.GetNextDocument(doc)

    Forall id In Listeg
    If (Listtag(id) = doc.MJ_GRID(0)) And (Cdat(id) <> Cdat(doc.CompletedDate(0))) Then
    'если в коллекции содержится документ с одинаковыми ид но другой датой то удаляем его из коллекции
    Call coll.DeleteDocument(doc)              
    End If         
    End Forall                     

    Set doc = doc1
    Wend
    Спасибо за советы, низнаю кому плюс ставить)
     
Загрузка...

Поделиться этой страницей