search

Use the [search] context with [founditems] to easily retrieve records from a database.
The following tags are available inside a [search] context:
TagDescription
[numfound]A number indicating how many records matched the search request.
[sum field=fieldName]Calculates the numerical sum of all the found records, using the fieldName column.
[avg field=fieldName]Calculates the numerical average of all the found records, using the fieldName column.
[min field=fieldName]Calculates the numerical minimum of all the found records, using the fieldName column.
[max field=fieldName]Calculates the numerical maximum of all the found records, using the fieldName column.
[founditems]...[/founditems]Place a [founditems] loop inside a [search], to display all the matching records. Any database field names may be used inside the [founditems] loop
[replacefounditems]...[/replacefounditems]Loops though all the found items and replaces text in each record with the specified new data.
[shownext]...[/shownext]Is used to build pagination

Fundamental Search Structure
[search criteria]
    [founditems]Search results[/founditems]
[/search]

It really is that simple. Any search criteria may be specified, and as many [search] contexts may be included in a template as required, [search] may be 'nested' them inside of each other to create relational searches among multiple databases.

Example WebDNA code:
[search db=customers.db&eqCITYdata=Chicago]
  Search returned [numfound] items
  [founditems]
    <img src="[picture]">
    [name], [address], [city]
  [/founditems]
  [shownext]
    Pagination links may be placed here
  [/shownext]
[/search]

To display results (using simple fieldname tags), place a [founditems]...[/founditems] context inside the [search] context. [founditems] will loop through the matching records.

In addition to [founditems], three other special tags are valid within the search, but NOT WITHIN the [founditems] tags.

1) [numfound] will report the number of records matching the search criteria.

2) [shownext] [/shownext] will manage pagination.

3) [replacefounditems] [/replacefounditems] will replace specified fields with new values as each matching record is found.

SQL/ODBC Note: To search through an ODBC-compliant database, use the [SQL] context, not [search].

Search Critera
Search criteria are strung together in the opening [search] tag, and separated with ampersands (&).
[search db=yourdatabase.db&eqCITYdata=Chicago&ZIPCODEsumm=t&ZIPCODEsort=1&max=25&startat=[starthere]]

Database Source (required)
db=yourdatabase.db
  OR
table=tablename

The source of your data can be either a database file on the server or a table (temporary 'in line' database table that is local to the template and not part of the global database cache.)

Data to look for (required)
eqCITYdata=Chicago

The data to search for must be indicated by specifying the field to look in, and the data to look for. See "Search Data" for how to refine this search with comparisons, partial strings, multiple fields, ranges, plus other options.

Sort Order
LASTNAMEsort=1

Define the sort order with sort. See sort for how to refine the sort using random, ascending, descending, no sorting, etc. There are two formats for defining sort.

Summary
ZIPCODEsumm=t

Summary will return just one record from each matching set of values. Use Summary to create headings and initiate subsearches. Sorting on the field summarized is also possible.

Data Format
DEADLINEtype=date
CLASSTIMEtype=time
INVENTORYtype=num

Unless otherwise specified, data will be treated alphabetically. This will cause 10 to appear before 2, and 11/30/2025 to appear before 02/28/2025. This applies to both sorting and to finding data using ranges, greater than, less than, etc. In the case of numbers of fixed length, such as zip codes and phone numbers, they will sort properly alphabetically, so there's no need to specify that field as a number.

Maximum to display on each page
max=25

Contrary to what this looks like, maximum only specifies how many results to display per page. The search will still find all the records requested, but when used with [shownext] context to manage pagination.

Search comparisons


Multiple Fields
You may search on more than one field.
eqStateData=New York&geCountyPopData=20000

Required Match
Add rq to the end to require the data be found. Otherwise, in the above example you would get other states with counties of over 20,000 population, and all New York counties, not just the big ones. Using rq makes this an AND comparison.
eqStateDatarq=New York&gecountiesDatarq=20

Sometimes you want to match one field and another field at the same time -- this if often called "anding fields together". Examples are "Find all people whose first name is Grant and last name is Hulbert" or perhaps "Find all houses that have more than 5 bedrooms and a fireplace and 2 bathrooms".

By default, if you do not specify certain fields are required to match, they are "or-ed" together, which in the above examples would read like "Find all people whose first name is Grant or last name is Hulbert" or perhaps "Find all houses that have more than 5 bedrooms or a fireplace or 2 bathrooms".

Important: WebDNA automatically 'ranks' the best-match results to the top of the list of found items. In the "or-ed" example above, all the houses that have more than 5 bedrooms and a fireplace and 2 bathrooms are shown at the top of the list. Houses that match 2 out of the 3 criteria are listed just below those, and finally houses that only match one of the criteria are listed last. You can override this standard ranking by forcing a different sort order.

typically "and" will find fewer matches in a database, because it is more restrictive -- the chances of finding a house that matches all 3 criteria simultaneously is far lower than finding a house that matches any one of the criterion individually.


To require particular fields to match during a search, put the letters "rq" after the data specifier, as in the following examples:
FirstName is Grant and LastName is HulberteqFirstNamedatarq=Grant&eqLastNamedatarq=Hulbert
Bedrooms > 5 and fireplace is True and Bathrooms is 2grBedsdatarq=5&eqFireplacedatarq=T&eqBathsdatarq=2

You can make all fields required in one simple step by putting "AllReqd=T" into the form.

The results file would contain a [founditems] loop that fills with all the matching records, and the resulting HTML would be sent back to the browser.

you can also embed a [search] context in a template. Any browser accessing that HTML page (no special commands required - just link to the page) will see the 'live' search results. It might look like the following


Here's an embedded search:
[search db=People.db&eqFirstNameDatarq=Grant&eqLastNamedatarq=Hulbert]
[founditems]
[FirstName], [Address], [City], [State], [Zip]<br>
[/founditems]
[/search]

Search one field two different ways


Search two fields at once
Both of these conditions are handled by grouping fields and it warrants its own section. Please refer to "Searching multiple fields" below.

Comparisons
You tell WebDNA how to compare by putting the two-letter comparison code in front. For instance, using gr means "Field value must be 'greater than' your search word"
grCountyPopData=20000

eqequal to
nenot equal to
grgreater than.
gegreater than or equal to
lsless than
leless than or equal to
rnrange. Specify two values separated by spaces (or any other delimiter specified by wbrk; i.e., ...&wbrk=,&...). The values may be dates, numbers, or text. If date, time or number, you must specify what type of data by using fieldnametype=xxx (where xxx is num, date or time).

Example: rnBirthdaydata=02/28/2025 08/31/2025&Birthdaytype=date
Note: When specifying a range, the smaller value must precede the larger value, i.e. rnZipCodedata=92069 93090, not rnZipCodedata=93090 92069.
mrminimum range value: if no maximum then ge is used instead
mx maximum range value: if no minimum than le is used instead
clclose to (numeric only). clZipCodedata=92069&clZipCodedata=10 finds all records whose ZipCode field is within 10 of 92069 (92059 - 92079)
bwbegins with
ewends with (from 8.6)
wsInterpret the words as a single string to be matched (including spaces etc.) This lets you find entire phrases, like "Joe enjoys butter" only if those 3 words are next to each other in that order, including spaces (unlike wa and wo, below)
waSeparate the words and "and" them together (all must match). Searching for 3 words using wa will match only if all 3 are in the field, but not necessarily next to each other.
woSeparate the words and "or" them together (at least one must match - default option for text). Search for 3 words using wo will match if any one of them matches.
wnword not equal - none of the words match text in the specified field
Word breaks: Use Wbrk to define what constitutes a word. By default, a space is a word delimiter, but you can define your own delimiter(s) using wbrk; example: fieldnameWbrk=,-;.
Word position in field: Use Word to define where you want the word to be found. Example: fieldnameWord=ww
ssSubString match. Looks for word anywhere, even inside larger words. Finds "I like typographic conventions" and "This is a graphic" and "Graphical user interfaces are cool."
wwWhole Word match. Looks for whole word; ignores if found inside a larger word. Finds "This is a graphic"
swStart of Word. Looks for word at the beginning of words. Finds "This is a graphic" and "Graphical user interfaces are cool."
Case sensitivity: Conducts case sensitive searches.
Examples:
fieldnameCase=t
AllCase=t (apply to all fields)
Finding Empty Fields and Find All
[blank] is a special WebDNA tag available in searches to explicitly find empty records. In practice, it is more often used to find records which are NOT empty, which is one way to "find all". Here are two popular ways to Find All:

nefieldnameDatarq=[blank]
nefieldnameDatarq=FindAll

The second example, of course, assumes you don't have a field value of FindAll.

Alternately, you can use the form FieldNameBLNK=T, which makes it possible to use radio buttons or checkboxes to let the visitor decide how they want to search for blank fields. If you want to apply this to all the fields in your search at once, then set allBLNK=T.

Searching multiple fields


One case you would need to do this would be in a general database search. If you want your users to search a catalog, you can let them search across the title, description, keywords, and any other field, such as author, manufacturer, etc. here is how you would do this:
group1field=title+description+keywords&wogroup1data=Bird

"group1" becomes the name of the combined field, and is used just like a regular fieldname with the data parameter. In this case, all three fields are searched and if Bird is found in any of them, the record will be retrieved.

WARNING: Grouping WILL NOT work if your field names contain a "-" (hyphen).

Searching the same field in two different ways
Sometimes you need to compare a value two different ways, but the search parameter will only accept a fieldname once. In this case, create two group fields like this:
group1field=zipcode&group2field=zipcode
and do what you need to do in your search; for example:
negroup1datarq=08055&rngroup2datarq=08001 08099
In this case, all the zip codes in one area are found, but one of them is excluded (perhaps the zip code that is currently being highlighted elsewhere on the page.)

When assigning groups, you must name them sequentially, without skipping numbers.


If you plan to work on several groups, the groupfield definitions must be placed at the beginning of the search string. For instance

group1field=title+description&wogroup1data=Bird&group2field=title+keyword&wogroup2data=Bird

has to be written in this order:

group1field=title+description&group2field=title+keyword&wogroup1data=Bird&wogroup2data=Bird


Sorting the results


A WebDNA search query allows you to sort and subsort your records in many ways. You may also summarize your records, and by using nested searches, create subheads.

Hierarchy
You can subsort on as many fields as necessary. By default, sort order is ascending, alphabetically. By using a prefix (see table below), you can change this default. By using fieldnametype=num/date/time, you tell WebDNA to sort either numerically, by date, or by time.

Assuming your database contains state, city, and citypop fields:

StateSort=1&CitySort=2

(Cities appear alphabetically, grouped by State)

StateSort=1&deCityPopSort=2&CityPopType=num&CitySort=3

(Cities appear in order of largest first, grouped by State. In the rare case that two cities have the exact same population, then they would be sorted alphabetically. Note the use of type=num to tell WebDNA to treat that field numerically. This is important. )

You cannot skip a number in the sorting hierarchy.


See the Summary section for ways to use Sorting and Summaries together

asascending (the default, if nothing specified)
dedescending
rarandom
Maintain randomness: Sometimes you need a series of random sorts to always present the exact same 'random' order. You can force the randomizer to return items in the same order if you add another parameter "RandSeed=879" (or any other integer number). This is most helpful when you use [ShowNext] and you need each successive set of links to predictably return the results in the same order.
RandSeed=integer
No sorting at all: Results are displayed in exactly the same order they appear in the database file.
Rank=off


Summaries


Create Headings
If we do two searches on a database of cities and states, we can create a heading for each state, and list the cities below. The first search will sort and summarize by state. Within the [FoundItems] of that search, we perform a second search based on field values from the first search.

[search db=yourdatabase.db&neStatedata=[blank]&StateSort=1&StateSumm=t]
[founditems]
<b>[State]</b> <p>
[search db=yourdatabase.db&eqStatedata=[state]&CitySort=1]
[founditems]
[city], population [citypop] <br>
[/founditems]
[/search]
[/founditems]
[/search]


When this plays out on the server, WebDNA will sort by state, but only return the first record of each state. As it finds each one, it displays the state name in bold, inserts a paragraph tag, then performs a new search for that state's cities (inserting the known state name in the [search]), then lists the cites with a line break tag after each one. Then it goes to the next state and repeats the process until the last state is taken care of.

Counting Unique Values
Working from the above example, maybe all we want is to know how many cites are in each state. We will use almost the same code to determine this, but won't display the cites at all.

[search db=yourdatabase.db&neStatedata=[blank]&StateSort=1&StateSumm=t]
[founditems]
<b>[State]</b>
[search db=yourdatabase.db&eqStatedata=[state]]
has [numfound] cities.<p>
[/search]
[/founditems]
[/search]


This time, WebDNA finds one record for each state as before, but this time, the second search doesn't care about sorting the cities, nor do we need the [foundItems] to display them. However, WebDNA still went to all the effort to find the cities that go with each state, and we can use [numfound] to get that value.

Want to grab the population of each state, by adding the populations of the cities within? No problem with WebDNA. It is easy using the [math] context.

Word Breaks and Field Breaks


Searches for whole words

Normally WebDNA searches for any text in a field, regardless of where it is in a sentence or even if it is in the middle of a word. You can tell WebDNA to search for whole words (letters surround by spaces, commas, etc.) or only the beginning of a word by setting word-break options.

You can define your own custom list of word break characters with wbrk=. By adding Descriptionwbrk=.,- to your search causes user-entered text surrounded by those characters in the HTML form field Description to be considered as individual words.


If your database has a field called "Description," and you want to look for records containing "graph" only at the beginning of words in the Description field, the URL would look like this:

[search db=somebase.db&woDescriptiondata=graph&Descriptionword=sw&]


word
ssDescriptionword=ss looks for "graphic" and finds it anywhere inside phrases such as: "I like typographic conventions" and "This is a graphic" and "Graphical user interfaces are cool."
wwDescriptionword=ww looks for "graphic" and will not find it inside phrases such as: "I like typographic conventions". It will be found inside "This is a graphic."
swDescriptionword=sw looks for "graphic" at the beginning of words, like "This is a graphic" and "Graphical user interfaces are good", but will not find it inside "I like typographic conventions."


FBRK (field break) option for WW, and SW field comparisons.

Specifies the delimiters used when doing a word compare in the field data itself. Thus:
woDESCRIPTIONdatarq=2&DESCRIPTIONword=WW&DESCRIPTIONfbrk=[url],[/url]

in the search string would not find a result if the field data is "400.2", whereas it would if the FBRK option was not specified.

Basically, "wbrk" tells WebDNA how to break up the values you pass in your search context, while "fbrk" tells WebDNA how to break up the values stored in the database.