From fb6729d0b5de7067ff7f5752f108140f3645d302 Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Mon, 23 Apr 2012 13:11:11 +0000
Subject: [PATCH] A bit more on search base, scope, and filters

---
 opendj3/src/main/docbkx/dev-guide/chap-reading.xml |  193 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 190 insertions(+), 3 deletions(-)

diff --git a/opendj3/src/main/docbkx/dev-guide/chap-reading.xml b/opendj3/src/main/docbkx/dev-guide/chap-reading.xml
index 99b4af2..b7898bb 100644
--- a/opendj3/src/main/docbkx/dev-guide/chap-reading.xml
+++ b/opendj3/src/main/docbkx/dev-guide/chap-reading.xml
@@ -20,7 +20,7 @@
   !
   ! CCPL HEADER END
   !
-  !      Copyright 2011 ForgeRock AS
+  !      Copyright 2011-2012 ForgeRock AS
   !    
 -->
 <chapter xml:id='chap-reading'
@@ -143,10 +143,197 @@
     }
 }</programlisting>
  </section>
- 
+
+ <section xml:id="basedn-and-scope">
+  <title>Setting Search Base &amp; Scope</title>
+
+  <para>Directory servers organize entries somewhat like a file system.
+  Directory data is often depicted as an upside-down tree.</para>
+
+  <mediaobject xml:id="figure-ldap-tree">
+   <alt>Directory data is often depicted as an upside-down tree.</alt>
+   <imageobject>
+    <imagedata fileref="images/ldap-tree.png" format="PNG" />
+   </imageobject>
+   <textobject>
+    <para>This figure shows three levels, the base DN for the suffix, a couple
+    of organizational units, and three user entries.</para>
+   </textobject>
+  </mediaobject>
+
+  <para>In the figure shown above, entries are represented by the relevant
+  parts of their DNs. The entry with DN <literal>dc=example,dc=com</literal>
+  is the base entry for a suffix. Under the base entry, you see two
+  organizational units, one for people, <literal>ou=People</literal>, the other
+  for groups, <literal>ou=Groups</literal>. The entries for people include
+  those of Babs Jensen, Kirsten Vaughan, and Sam Carter.</para>
+
+  <para>When you are searching for a person's entry somewhere under
+  <literal>dc=example,dc=com</literal>, you can start from
+  <literal>dc=example,dc=com</literal>, from
+  <literal>ou=People,dc=example,dc=com</literal>, or if you have enough
+  information to pinpoint the user entry and only want to look up another
+  attribute value for example, then directly from the entry such as
+  <literal>cn=Babs Jensen,ou=People,dc=example,dc=com</literal>. The DN of
+  the entry where you choose to start the search is the base DN for the
+  search.</para>
+
+  <itemizedlist>
+   <para>When searching, you also define the scope. Scope defines what entries
+   the server considers when checking for entries that match your search.</para>
+   <listitem>
+    <para>For <literal>SearchScope.BASE_OBJECT</literal> the server considers
+    only the base entry.</para>
+    <para>This is the scope you use if you know the full DN of the object
+    that interests you. For example, if your base DN points to Babs Jensen's
+    entry, <literal>cn=Babs Jensen,ou=People,dc=example,dc=com</literal>, and
+    you want to read some of Babs's attributes, you would set scope to
+    <literal>SearchScope.BASE_OBJECT</literal>.</para>
+   </listitem>
+   <listitem>
+    <para>For <literal>SearchScope.SINGLE_LEVEL</literal> the server considers
+    all entries directly below the base entry.</para>
+    <para>You use this scope if for example you want to discover organizational
+    units under <literal>dc=example,dc=com</literal>, or if you want to find
+    people's entries and you know they are immediately under
+    <literal>ou=People,dc=example,dc=com</literal>.</para>
+   </listitem>
+   <listitem>
+    <para>For <literal>SearchScope.SUBORDINATES</literal> the server considers
+    all entries below the base entry.</para>
+    <para>This scope can be useful if you know that the base DN for your search
+    is an entry that you do not want to match.</para>
+   </listitem>
+   <listitem>
+    <para>For <literal>SearchScope.WHOLE_SUBTREE</literal> (default) the server
+    considers the base entry and all entries below.</para>
+   </listitem>
+  </itemizedlist>
+
+  <para>In addition to a base DN and scope, a search request also calls for a
+  search filter.</para>
+ </section>
+
  <section xml:id="about-filters">
   <title>Working With Search Filters</title>
-  <para>TODO</para>
+
+  <para>When you look someone up in the telephone directory, you use the value
+  of one attribute of a person's entry (last name), to recover the person's
+  directory entry, which has other attributes (phone number, address). LDAP
+  works the same way. In LDAP, search requests identify both the scope of the
+  directory entries to consider (for example, all people or all organizations),
+  and also the entries to retrieve based on some attribute value (for example,
+  surname, mail address, phone number, or something else). The way you express
+  the attribute value(s) to match is by using a search filter.</para>
+
+  <para>LDAP search filters define what entries actually match your request.
+  For example, the following simple equality filter says, "Match all entries
+  that have a surname attribute (sn) value equivalent to Jensen."</para>
+
+  <literallayout class="monospaced">(sn=Jensen)</literallayout>
+
+  <para>When you pass the directory server this filter as part of your search
+  request, the directory server checks the entries in scope for your search to
+  see whether they match.<footnote><para>In fact, the directory server probably
+  checks an index first, and might not even accept search requests unless it
+  can use indexes to match your filter rather than checking all entries in
+  scope.</para></footnote> If the directory server finds entries that match,
+  it returns those entries as it finds them.</para>
+
+  <para>The example, <literal>(sn=Jensen)</literal>, shows a string
+  representation of the search filter. The OpenDJ LDAP SDK lets you express
+  your filters as strings, or as <literal>Filter</literal> objects. In both
+  cases, the SDK translates the strings and objects into the binary
+  representation sent to the server over the network.</para>
+
+  <variablelist>
+   <para>Equality is just one of the types of comparisons available in LDAP
+   filters. Comparison operators include the following.</para>
+
+   <varlistentry>
+    <term>=</term>
+    <listitem>
+     <para>Equality comparison, as in <literal>(sn=Jensen)</literal>.</para>
+     <para>This can also be used with substring matches. For example, to match
+     last names starting with <literal>Jen</literal>, use the filter
+     <literal>(sn=Jen*)</literal>. Substrings are more expensive for the
+     directory server to index. Substring searches therefore might not be
+     permitted for many attributes.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>&lt;=</term>
+    <listitem>
+     <para>Greater than or equal to comparison, which works
+     alphanumerically.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>&gt;=</term>
+    <listitem>
+     <para>Greater than or equal to comparison, which works
+     alphanumerically.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>=*</term>
+    <listitem>
+     <para>Presence comparison. For example, to match all entries having a
+     <literal>userPassword</literal>, use the filter
+     <literal>(userPassword=*)</literal>.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>~=</term>
+    <listitem>
+     <para>Approximate comparison, matching attribute values similar to the
+     value you specify.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>[:dn][:<replaceable>oid</replaceable>]:=</term>
+    <listitem>
+     <para>Extensible match comparison. For example,
+     <literal>(uid:dn:=bjensen)</literal> matches entries where
+     <literal>uid</literal> having the value <literal>bjensen</literal> is
+     a component of the entry DN.
+     <literal>(lastLoginTime:1.3.6.1.4.1.26027.1.4.5:=-13w)</literal> matches
+     entries with a last login time more recent than 13 weeks.</para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+
+  <variablelist>
+   <para>You can use boolean operators to build complex filters when a single
+   filter comparison is not enough to express what to match.</para>
+
+   <varlistentry>
+    <term>&amp;</term>
+    <listitem>
+     <para>This binary operator matches entries that belong to the intersection
+     of the two component filters, for example all users named Barbara whose
+     last name starts with Jen,
+     <literal>(&amp;(givenName=Barbara)(sn=Jen*))</literal>.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>|</term>
+    <listitem>
+     <para>This binary operator matches entries that belong to the union of the
+     two component filters, for example all the users named Jensen or Smith,
+     <literal>(|(sn=Jensen)(sn=Smith))</literal>.</para>
+    </listitem>
+   </varlistentry>
+   <varlistentry>
+    <term>!</term>
+    <listitem>
+     <para>This unary operator matches entries that do not match the filter.
+     Use this in complex filters when you have already narrowed the scope,
+     for example all users named Jensen whose first name is not Barbara,
+     <literal>(&amp;(sn=Jensen)(!(givenName=Barbara)))</literal>.</para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
  </section>
 
  <section xml:id="send-search-request">

--
Gitblit v1.10.0