Thanks DM.<div>The multi-variable dependency description of the index was helpful.<br><br><div class="gmail_quote">On Thu, Nov 4, 2010 at 3:20 PM, DM Smith <span dir="ltr">&lt;<a href="mailto:dmsmith@crosswire.org">dmsmith@crosswire.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

  
    
  
  <div bgcolor="#ffffff" text="#000000">
    I thought I&#39;d outline the variables that go into building an index
    that can be reliably searched.<br>
    <br>
    The unit of an index is called a Document. In our case, this is a
    verse, a dictionary entry, ..., anything that SWORD identifies as a
    keyed piece of information.<br>
    <br>
    A document consists of one or more fields having content. We have
    several: content, note, strong, ..., with content being the default.
    One specifies a field search as with:<br>
        strong:H3068<br>
    If no field is specified, the default is searched.<br>
    <br>
    It is possible to have fields that are not searchable but merely
    store information. We do this with the key for the item. That way,
    we know what we have gotten back from a search.<br>
    <br>
    Each field is built independently from the others. Each has its own
    analyzer. Though two fields might have the same, it is best to
    ignore that. An analyzer consists of a tokenizer which splits up
    text into a stream of tokens and filters applied to that stream.<br>
    <br>
    Generally we think of tokens as words, but it is a bit more
    complicated than that. The StandardAnalyzer also tries to identify
    phone numbers, acronyms, URLs, and other common English constructs.
    It also uses white space as word delimiters and punctuation as a
    hint to word boundaries. SWORD uses the StandardAnalyzer, but JSword
    does not. It uses a variation of the SimpleAnalyzer, which uses
    white space and punctuation as boundaries.<br>
    <br>
    One of the complexities is that not all languages use the same rules
    for word boundaries. E.g. Chinese uses one glyph per word and spaces
    are not used to separate words. Thai does not use white space and it
    looks as if all the letters are run together. Ancient Greek also ran
    words together consisting of all capital letters. These need to be
    treated specially. The typical approach with Chinese, is to do
    bi-gram searching. That is, if looking for a single glyph, look for
    just that, but if looking for multiple glyphs, break it up into
    pairs and look for those pairs. For Thai, the typical approach is to
    use a dictionary and Unicode tables to break up the string of
    characters into words.<br>
    <br>
    Regarding Unicode, it has progressed over the years with several
    versions being released. And each version of Java implements a
    version of Unicode.  Quoting the JLS:
    (<a href="http://java.sun.com/docs/books/jls/third_edition/html/lexical.html" target="_blank">http://java.sun.com/docs/books/jls/third_edition/html/lexical.html</a>)<br>
    <blockquote type="cite">Versions of the Java programming language
      prior to 1.1 used Unicode version 1.1.5. Upgrades to newer
      versions of the Unicode Standard occurred in JDK 1.1 (to Unicode
      2.0), JDK 1.1.7 (to Unicode 2.1), J2SE 1.4 (to Unicode 3.0), and
      J2SE 5.0 (to Unicode 4.0).<br>
    </blockquote>
    From what I understand Java 6 is also Unicode 4.0 and Java 7 is
    planned to be Unicode 5.1.<br>
    <br>
    Turns out that IBM&#39;s Java does not have the same implementation as
    Sun (now Oracle). I don&#39;t know about Android&#39;s Java, which seems to
    be a variant of Harmony.<br>
    <br>
    From a practical level this means that if there is a reliance on a
    specific version and comparable implementation of Unicode then one
    needs to stick with that. That is an index built with Java 1.4 may
    not be the same as one built with Java 5. And one built with Java 5
    might not be the same as one built with Harmony/Android.<br>
    <br>
    This is especially true with Thai. IBM&#39;s Java does not have a decent
    break iterator while Sun&#39;s does. Who knows about Harmony? One way to
    get around this is to use ICU4J to do the analysis. And another is a
    UAX29Tokenizer, which tokenizes based on the Unicode tables (5.0 if
    I remember). With Lucene 3.0 and later, this is possible. And the
    code might be able to be back ported to 2.9.x series.<br>
    <br>
    Once tokens are identified, they are filtered. There are various
    filters that might be used (note, I&#39;m doing this from memory so the
    names are a bit off. It will give the idea):<br>
    LowercaseFilter - lower case the letters. Note, some languages don&#39;t
    have both upper and lower.<br>
    FoldingFilter - removes accents, diacriticals, pointing and the
    like. There are some specific language foldings such as final sigma
    to sigma.<br>
    CompoundWordFilter - splits compound words into parts. Very useful
    for German. Typically this is dictionary based.<br>
    StopWordFilter - remove noise words such as a, the, in, ..., as
    provided in a list. From a theological perspective, &quot;In Christ&quot;
    might be an important find.<br>
    *StemmingFilter - Converts word into their stem/root form. Note,
    this is language specific, thus the *. Generally this is rule based,
    but sometimes is dictionary driven.<br>
    Note that the StandardAnalyzer filters stop words, but does no
    folding or stemming.<br>
    <br>
    ICU normalization generally needs to precede filtering. There are
    two basic forms: Composed (NFC) and decomposed (NFD). For each of
    these there is a canonical &#39;K&#39; variant, NFKC and NFKD.
    Simplistically, with decomposed, the base character is followed by
    its decorations (e.g. accents). In composed form, they are combined
    into one. Our modules, in order to conserve space, typically do NFC.<br>
    <br>
    Some things to note:<br>
    The order of filters may be important.<br>
    The tables that the filters use are important.<br>
    <br>
    Each release of Lucene has varied one or more of these things.
    Typically, this is due to a bug fix.<br>
    <br>
    The goal is that a token stream for a field be the same for indexing
    as for searching. If they differ, results are unpredictable.<br>
    So to put this together, if any of the following changes, all bets
    are off:<br>
        Tokenizer (i.e. which tokenizer is used)<br>
        The rules that a tokenizer uses to break into tokens.<br>
        The type associated with each token (e.g. word, number, url,
    .... We ignore this so it doesn&#39;t matter.)<br>
        Presence/Absence of a particular filter<br>
        Order of filters<br>
        Tables that a filter uses<br>
        Rules that a filter encodes<br>
        The version and implementation of Unicode being used (whether
    via ICU, Lucene and/or Java)<br>
        The version of Lucene (e.g. every version of Lucene has fixed
    bugs in these components.)<br>
    And if we did highlighting:<br>
        The relative position of each token.<br>
        <br>
    What is planned is to record this along with the index in a
    manifest. If the manifest changes for a field that is exposed
    through the app, then the index should be rebuilt. It may be that
    JSword will be able to adapt to a particular manifest. For example,
    it is under programmers control whether stemming and/or stop filters
    are applied. (Right now, defaults are assumed.) If an index is built
    with stemming but not stop words, then the searching analyzer can be
    built to match. It won&#39;t matter that the list of stop words has
    changed.<br>
    <br>
    To have them on a server means that we need to keep versions around
    and to be able to request them. We need to support people who don&#39;t
    upgrade their app to match the latest index.<br>
    <br>
    Hope this is helpful.<br>
    <br>
    In Him,<br>
        DM<div class="im"><br>
    <br>
    <br>
    On 11/04/2010 11:26 AM, Martin Denham wrote:
    </div><blockquote type="cite"><div><div></div><div class="h5">
      <div>Does anybody know any reason why a search for &#39;blessed&#39; does
        not return any search results in ESV but searching for &#39;bless&#39;
        work perfectly?</div>
      <div><br>
      </div>
      When I download  BibleDesktop (JSword) generated indexes to And
      Bible I have noticed that some searches like &#39;blessed&#39; stop
      working but I can&#39;t figure out what the problem is and would
      appreciate some pointers as to areas to look.
      <div>
        <br>
      </div>
      <div>I have checked that the correct Analyzer is being used but I
        am not sure what else to check or if the &#39;blessed&#39;/&#39;bless&#39; issue
        might point to a specific problem area.</div>
      <div><br>
      </div>
      <div>
        The plan is to download pre-created indexes to And Bible and in
        theory those indexes should be generated by JSword but currently
        And Bible can only use indexes it creates itself or which have
        been created by CLucene/Sword.</div>
      <div><br>
      </div>
      <div>All advice, opinions, and comments are appreciated.</div>
      <div><br>
      </div>
      <div>Many thanks</div>
      <div>Martin</div>
      <div><br>
      </div>
      <div><br>
      </div>
      </div></div><pre><fieldset></fieldset>
_______________________________________________
jsword-devel mailing list
<div class="im"><a href="mailto:jsword-devel@crosswire.org" target="_blank">jsword-devel@crosswire.org</a>
<a href="http://www.crosswire.org/mailman/listinfo/jsword-devel" target="_blank">http://www.crosswire.org/mailman/listinfo/jsword-devel</a>
</div></pre>
    </blockquote>
    <br>
  </div>

<br>_______________________________________________<br>
jsword-devel mailing list<br>
<a href="mailto:jsword-devel@crosswire.org">jsword-devel@crosswire.org</a><br>
<a href="http://www.crosswire.org/mailman/listinfo/jsword-devel" target="_blank">http://www.crosswire.org/mailman/listinfo/jsword-devel</a><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Regards,<br>Sijo<br>
</div>