IBM®
Skip to main content
    Country/region select      Terms of use
 
 
   
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks  >  Lotus  >  Forums & community  >  Best Practice Makes Perfect

Best Practice Makes Perfect

A collaboration with Domino developers about how to do it and how to get it right in Domino

Joseph LeMay writes (in reference to using db.Search vs. finding documents in a view):
> when I need to build a collection of documents, I usually just build a view and sort it by some key, then use notesView.GetAllDocumentsByKey(key).  Is this inefficient?  I can't think of a time I've used db.search.  I suppose adding another view increases the size of the db, and gives it another view to index, which can cause a performance hit, but I haven't run into a situation yet where this has really slowed things down noticeably

If you can use a view, I think it's generally the best-performing choice. But you can't always use a view, and performance is not always the paramount consideration.

As we saw in the timing tests I did, accessing documents through a view is very fast compared to other methods, if the pool of candidate documents is all the documents. Adding a view does make your nsf larger and slows the application generally -- or so I've been told; I've never tried to measure by how much (anyone have stats?). But if you can use a view that you needed anyway for a different reason, this is not a factor.

But there are times that a view doesn't work as well as other methods:

  • Unless you use a date-based selection formula, the stored view index contains all the documents in the database that match your selection formula (and if you do use a date-based selection, the index must be rebuilt with each use, so it's slow). A view's not as useful if you want to limit to documents touched since a certain date -- a common situation in scheduled agents.
  • The view selection criteria are static, whereas you can use code to construct a db.Search with any formula you like, determined at runtime. You can change the view selection formula at runtime with LotusScript code (assuming the agent's signer has Designer access) but this is not a good way to do a search. You lose the performance advantage of views, because all the documents have to be reviewed for reindexing. Because the view indexer uses the summary instead of the entire document, it might be faster than the same formula in db.Search, but the view indexer has to do the extra work of sorting the documents and writing the new index to disk ($$$), so overall you might not get any performance boost by setting view.SelectionFormula vs. using db.Search -- and the code is more complex.
  • It's hard to use a view to find documents in a range, or where a field "contains" a string, or where field != value, or any other criteria which are not field value.
As a side note, the new NotesDocumentCollection methods I just wrote about, are nice because they expand the number of cases where a view search is useful in finding documents. Because before, you could only easily do an "and" condition, and now it's fairly simple to do an "or" or "and not", or to do an "and" that doesn't require a single view sorted by both keys. For instance, suppose you have a view sorted by Expertise and then by Country, and you want to find people skilled in "Swimming" who live in "Grand Fenwick". In current versions, you could do something like:

Dim key(0 to 1) As String
key(0) = "Swimming"
key(1) = "Grand Fenwick"
Set collResult = view.GetAllDocumentsByKey(key, True)

(Note: be careful with GetAllDocumentsByKey, because the default matching is not exact, so you might update the documents for "Marshmallow" when you only meant to update "Marsh")

However, this requires a view that's sorted by both keys, which makes it harder to double-up the view with some other use. Whereas in version 8.0, you can use two views, one sorted by Expertise and one sorted by Country (which you probably needed these views anyway), find the matching documents in each view, and then Intersect them:

Set collA = viewByCountry.GetAllDocumentsByKey("Grand Fenwick", True)
Set collB = viewByExpertise.GetAllDocumentsByKey("Swimming", True)
Call collA.Intersect(collB)
' limit to docs where (A and B) is true.

It's less efficient, but needing fewer views is also worth something. And if you wanted to find all the people in Grand Fenwick who do not swim (because you're expecting a flood and need to enroll the non-swimmers in swim training), just use Subtract instead of Intersect. Or for the equivalent of "or", use Merge.

Doing the search this way is possible in pre-8.0 -- it's not that hard to write your own Subtract or Intersect functions -- but it's faster and simpler with the built-in methods; it saves your time and gives better performance (because the looping happens in the fast C++ code).

Complexity and code readability is also very important. While view searches might be the best-performing, you don't always get the easiest-to-understand code, especially when you use set operations on collections. By comparison, the following is simple and not much slower:

Set collResult = db.FtSearch( {([Country] = "} & Country & {") and not ([Expertise] = "} & Skill & {")}, 0) ' I'm assuming there are no quotes in the data.

Besides the code itself being less complex, you can see exactly what this does without having to switch screens to look at the design of a view. It's all right there in front of you. Compare the amount of time it takes to write this statement with the time it takes to create the view you need for a view-based search -- and the time you later have to spend figuring out what went wrong and re-creating the view after some other developer (or you yourself, after some time has passed) deleted the view, thinking it was unused.

Remember, your time is valuable -- the less you have to spend writing and maintaining code, the more slack you have to read my blog and do crossword puzzles. Only worry about performance when it really makes a difference -- CPU cycles are cheap.

Andre Guirard | 27 April 2007 01:01:00 AM ET | Plymouth, MN, USA | Comments (11)


 Comments

1) Thanks, Andre
Rob McDonagh | 4/27/2007 1:14:08 PM

This whole thread is very interesting, seeing not just the how/what but also the why, and discussing the various trade-offs.

2) NotesViewNavigator class
Joseph LeMay | 10/9/2007 6:12:37 PM

I wonder if you could comment on using the notesviewnavigator class to extract information from the documents you need as opposed to the NotesDocumentCollection class. Let me give you an example of a problem I was working on where it made sense to use it. I have a Contracts database, and each contract has change orders associated with it. Each change order has to show the amount of the original contract plus all previous change orders, and then the new total, so there's some math to do on each change order, and the more change orders you have, the more math there is. So what I'd have to do is

set dc = view.GetAllDocumentsByKey(ContractNo)

then loop through the dc by accessing the properties of each document.

But would I get a peformance kick if I did

set viewnav = view.createViewNavFromCategory(ContractNo)

then looped through the view entries?

3) Sorted?
Matt | 7/17/2009 4:51:31 PM

I thought the GetAllDocumentsByKey does not return sorted documents.

From the help: "Documents returned by this method are in no particular order..."

Is that wrong?

4) More about getting the docs you want
Andre Guirard | 7/17/2009 11:20:34 PM

@Matt, I not only agree with that statement in the help, I seem to recall writing it. Did I appear to be saying something different here?

5) Sorted
Matt | 7/20/2009 8:37:44 AM

The artical mentions sorting the views in a few ways. I thought you were implying the results were sorted, but it sounds like I just misunderstood.

I keep searching for a way to quickly filter documents and return them in a sorted order, but everything I try is just too slow for large databases.

6) More about getting the docs you want
Andre Guirard | 7/20/2009 9:07:49 AM

NotesViewEntryCollection is searchable and returns results in sorted order. Also, for general performance tips for big databases, see http://www.ibm.com/developerworks/lotus/documentation/d-ls-notesperformance/

7) Sorted
Aldrin | 7/27/2009 6:39:26 AM

I came across this as I've been searching the actual behavior when you intersect a NotesDocumentCollection into NotesViewEntryCollection.

If not intersected (intersect is not called), NotesViewEntryCollection is fine and the result is the same as how it's arranged in the source view - entries/documents are in correct order as shown in view

But, If Intersect() is called (to return only selected documents), intersected/remaining entries are scrambled?

8) Intersect screws up viewentrycollection sort order
George | 8/4/2009 9:29:18 AM

Aldrin is right, once a NotesViewEntryCollection is intersected with a Document Collection the NotesViewEntryCollection is not sorted as before intersection.

Is that a bug? or by design?

9) NotesViewEntryCollection bug or just dumb?
Giulio | 9/28/2009 8:56:11 PM

@George and Aldrin. I have observed the same porblem. You want to put a notesdocumentcollection into a sorted order of the view you selected the documents from.

But when you jam the document collection into a viewentry collection the viewentry collection does not enforce the sorted order, as you might expect.

I would not say it's a bug, but rather incomplete design. It would solve alot of problems to either :

1/ Be able to push a notesDocumentCollection into an empty viewentry collection to get the sort order. OR

2/ Apply a view index to a documentCollection to sort it with an extra parameter in the getalldocumentsByKeylike this :

set ndc = view.getAlldocumentsByKey("xxx", true, true);

Where the definition is

getAlldocumentsByKey(key as variant, exactMatch as boolean, SortOnDefaultIndex as boolean);

Just my 2.4cents worth..

10) More about getting the docs you want
Andre Guirard | 10/13/2009 2:34:24 PM

Intersect sort order issue reported as SPR # AGUD7WJQG8.

11) SPR # AGUD7WJQG8
Matt | 11/15/2010 9:23:23 AM

It says this bug has been fixed, but it still appears in 8.5.2. Please advise on the status of this issue.

 Add a Comment
Subject:
   
Name:
Comment:  (No HTML - Links will be converted if prefixed http://)
 
Remember Me?     Cancel

Search this blog 

Disclaimer 

    About IBM Privacy Contact