<h1><spanclass="section-number">11. </span>Searching for things<aclass="headerlink"href="#searching-for-things"title="Permalink to this headline">¶</a></h1>
<p>We have gone through how to create the various entities in Evennia. But creating something is of little use
if we cannot find and use it afterwards.</p>
<sectionid="main-search-functions">
<h2><spanclass="section-number">11.1. </span>Main search functions<aclass="headerlink"href="#main-search-functions"title="Permalink to this headline">¶</a></h2>
<p>The base tools are the <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_*</span></code> functions, such as <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_object</span></code>.</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span> rose = evennia.search_object(key="rose")
<p>What is returned from the main search functions is actually a <codeclass="docutils literal notranslate"><spanclass="pre">queryset</span></code>. They can be treated like lists except that they can’t modified in-place. We’ll discuss querysets in the <codeclass="docutils literal notranslate"><spanclass="pre">next</span><spanclass="pre">lesson</span></code><Django-queries>`_.</p>
</aside>
<p>Strings are always case-insensitive, so searching for <codeclass="docutils literal notranslate"><spanclass="pre">"rose"</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">"Rose"</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">"rOsE"</span></code> give the same results.
It’s important to remember that what is returned from these search methods is a <em>listing</em> of 0, one or more
elements - all the matches to your search. To get the first match:</p>
<p>Often you really want all matches to the search parameters you specify. In other situations, having zero or
more than one match is a sign of a problem and you need to handle this case yourself.</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>the_one_ring = evennia.search_object(key="The one Ring")
if not the_one_ring:
# handle not finding the ring at all
elif len(the_one_ring) > 1:
# handle finding more than one ring
else:
# ok - exactly one ring found
the_one_ring = the_one_ring[0]
</pre></div>
</div>
<p>There are equivalent search functions for all the main resources. You can find a listing of them
<aclass="reference internal"href="../../../Evennia-API.html"><spanclass="doc std std-doc">in the Search functions section</span></a> of the API frontpage.</p>
</section>
<sectionid="searching-using-object-search">
<h2><spanclass="section-number">11.2. </span>Searching using Object.search<aclass="headerlink"href="#searching-using-object-search"title="Permalink to this headline">¶</a></h2>
<p>On the <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code> is a <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> method which we have already tried out when we made Commands. For
this to be used you must already have an object available:</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> method wraps <codeclass="docutils literal notranslate"><spanclass="pre">evennia.search_object</span></code> and handles its output in various ways.</p>
<ulclass="simple">
<li><p>By default it will always search for objects among those in <codeclass="docutils literal notranslate"><spanclass="pre">obj.location.contents</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">obj.contents</span></code> (that is,
things in obj’s inventory or in the same room).</p></li>
<li><p>It will always return exactly one match. If it found zero or more than one match, the return is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>.</p></li>
<li><p>On a no-match or multimatch, <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> will automatically send an error message to <codeclass="docutils literal notranslate"><spanclass="pre">obj</span></code>.</p></li>
</ul>
<p>So this method handles error messaging for you. A very common way to use it is in commands:</p>
<p>Remember, <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> is the one calling the command. This is usually a Character, which
inherits from <codeclass="docutils literal notranslate"><spanclass="pre">DefaultObject</span></code>! This (rather stupid) Command searches for an object named “foo” in
the same location. If it can’t find it, <codeclass="docutils literal notranslate"><spanclass="pre">foo</span></code> will be <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>. The error has already been reported
to <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> so we just abort with <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code>.</p>
<p>You can use <codeclass="docutils literal notranslate"><spanclass="pre">.search</span></code> to find anything, not just stuff in the same room:</p>
<p>With <codeclass="docutils literal notranslate"><spanclass="pre">quiet=True</span></code> the user will not be notified on zero or multi-match errors. Instead you are expected to handle this
yourself and what you get back is now a list of zero, one or more matches!</p>
</section>
<sectionid="what-can-be-searched-for">
<h2><spanclass="section-number">11.3. </span>What can be searched for<aclass="headerlink"href="#what-can-be-searched-for"title="Permalink to this headline">¶</a></h2>
<p>These are the main database entities one can search for:</p>
<p>Most of the time you’ll likely spend your time searching for Objects and the occasional Accounts.</p>
<p>So to find an entity, what can be searched for?</p>
<sectionid="search-by-key">
<h3><spanclass="section-number">11.3.1. </span>Search by key<aclass="headerlink"href="#search-by-key"title="Permalink to this headline">¶</a></h3>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is the name of the entity. Searching for this is always case-insensitive.</p>
</section>
<sectionid="search-by-aliases">
<h3><spanclass="section-number">11.3.2. </span>Search by aliases<aclass="headerlink"href="#search-by-aliases"title="Permalink to this headline">¶</a></h3>
<p>Objects and Accounts can have any number of aliases. When searching for <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> these will searched too,
<p>If the above <codeclass="docutils literal notranslate"><spanclass="pre">rose</span></code> has a <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code><codeclass="docutils literal notranslate"><spanclass="pre">"Rose"</span></code>, it can now also be found by searching for <codeclass="docutils literal notranslate"><spanclass="pre">flower</span></code>. In-game
you can assign new aliases to things with the <codeclass="docutils literal notranslate"><spanclass="pre">alias</span></code> command.</p>
</section>
<sectionid="search-by-location">
<h3><spanclass="section-number">11.3.3. </span>Search by location<aclass="headerlink"href="#search-by-location"title="Permalink to this headline">¶</a></h3>
<p>Only Objects (things inheriting from <codeclass="docutils literal notranslate"><spanclass="pre">evennia.DefaultObject</span></code>) has a location. This is usually a room.
The <codeclass="docutils literal notranslate"><spanclass="pre">Object.search</span></code> method will automatically limit it search by location, but it also works for the
general search function. If we assume <codeclass="docutils literal notranslate"><spanclass="pre">room</span></code> is a particular Room instance,</p>
<h3><spanclass="section-number">11.3.4. </span>Search by Tags<aclass="headerlink"href="#search-by-tags"title="Permalink to this headline">¶</a></h3>
<p>Think of a <aclass="reference internal"href="../../../Components/Tags.html"><spanclass="doc std std-doc">Tag</span></a> as the label the airport puts on your luggage when flying.
Everyone going on the same plane gets a tag grouping them together so the airport can know what should
go to which plane. Entities in Evennia can be grouped in the same way. Any number of tags can be attached
<p>Tags can also have categories. By default this category is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> which is also considered a category.</p>
<h3><spanclass="section-number">11.3.5. </span>Search by Attribute<aclass="headerlink"href="#search-by-attribute"title="Permalink to this headline">¶</a></h3>
<p>We can also search by the <aclass="reference internal"href="../../../Components/Attributes.html"><spanclass="doc std std-doc">Attributes</span></a> associated with entities.</p>
<div><p>Searching by Attribute can be very practical. But if you plan to do a search very often, searching
by-tag is generally faster.</p>
</div></blockquote>
</section>
<sectionid="search-by-typeclass">
<h3><spanclass="section-number">11.3.6. </span>Search by Typeclass<aclass="headerlink"href="#search-by-typeclass"title="Permalink to this headline">¶</a></h3>
<p>Sometimes it’s useful to find all objects of a specific Typeclass. All of Evennia’s search tools support this.</p>
<p>If you have the <codeclass="docutils literal notranslate"><spanclass="pre">Rose</span></code> class already imported you can also pass it directly:</p>
<p>This last way of searching is a simple form of a Django <em>query</em>. This is a way to express SQL queries using
Python.</p>
</section>
<sectionid="search-by-dbref">
<h3><spanclass="section-number">11.3.7. </span>Search by dbref<aclass="headerlink"href="#search-by-dbref"title="Permalink to this headline">¶</a></h3>
<p>The database id or <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code> is unique and never-reused within each database table. In search methods you can
replace the search for <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> with the dbref to search for. This must be written as a string <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code>:</p>
<p>Since <codeclass="docutils literal notranslate"><spanclass="pre">#dbref</span></code> is always unique, this search is always global.</p>
<divclass="admonition warning">
<pclass="admonition-title">Warning</p>
<p>Relying on #dbrefs</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>You may be used to using #dbrefs a lot from other codebases. It is however considered
`bad practice` in Evennia to rely on hard-coded #dbrefs. It makes your code hard to maintain
and tied to the exact layout of the database. In 99% of cases you should pass the actual objects
around and search by key/tags/attribute instead.
</pre></div>
</div>
</div>
</section>
</section>
<sectionid="finding-objects-relative-each-other">
<h2><spanclass="section-number">11.4. </span>Finding objects relative each other<aclass="headerlink"href="#finding-objects-relative-each-other"title="Permalink to this headline">¶</a></h2>
<p>Let’s consider a <codeclass="docutils literal notranslate"><spanclass="pre">chest</span></code> with a <codeclass="docutils literal notranslate"><spanclass="pre">coin</span></code> inside it. The chests stand in a room <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>. In the dungeon is also
a <codeclass="docutils literal notranslate"><spanclass="pre">door</span></code>. This is an exit leading outside.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">chest</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">chest.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">dungeon</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.location</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> since it’s not inside something else.</p></li>
</ul>
<p>One can use this to find what is inside what. For example, <codeclass="docutils literal notranslate"><spanclass="pre">coin.location.location</span></code> is the <codeclass="docutils literal notranslate"><spanclass="pre">room</span></code>.
We can also find what is inside each object. This is a list of things.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[chest,</span><spanclass="pre">door]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">chest.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[coin]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code>, the empty list since there’s nothing ‘inside’ the coin.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.contents</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code> too.</p></li>
</ul>
<p>A convenient helper is <codeclass="docutils literal notranslate"><spanclass="pre">.contents_get</span></code> - this allows to restrict what is returned:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.contents_get(exclude=chest)</span></code> - this returns everything in the room except the chest (maybe it’s hidden?)</p></li>
</ul>
<p>There is a special property for finding exits:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.exits</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[door]</span></code></p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">coin.exits</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">[]</span></code> (same for all the other objects)</p></li>
</ul>
<p>There is a property <codeclass="docutils literal notranslate"><spanclass="pre">.destination</span></code> which is only used by exits:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">door.destination</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">outside</span></code> (or wherever the door leads)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">room.destination</span></code> is <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> (same for all the other non-exit objects)</p></li>
</ul>
</section>
<sectionid="summary">
<h2><spanclass="section-number">11.5. </span>Summary<aclass="headerlink"href="#summary"title="Permalink to this headline">¶</a></h2>
<p>Knowing how to find things is important and the tools from this section will serve you well. For most of your needs
these tools will be all you need …</p>
<p>… but not always. In the next lesson we will dive further into more complex searching when we look at