Indexing Metadata


  • Each document in the database includes a metadata section, stored in a special JSON object under the @metadata property.

  • This metadata is not part of the document's content but holds internal system information (used by RavenDB), such as the document ID, collection name, change vector, last modified timestamp, and more,
    as well as optional user-defined entries.

  • To learn how to access (get and modify) the metadata from your client code,
    see How to get and modify the metadata.

  • Content from metadata properties can be extracted and indexed within a static index, alongside content from the document fields. This allows you to query for documents based on values stored in the metadata.
    See the examples below.



Indexing metadata properties

  • To access a document's metadata, use the MetadataFor method, which is available in the C# LINQ string that is assigned to the map property in the PHP index class, as shown in the example below.

  • You can retrieve metadata values using one of two C# syntaxes:

    • Generic method syntax
      Use Value<T>() to retrieve and cast the metadata value to the expected type.
      This is type-safe and preferred when the type is known (e.g., DateTime).
    • Indexer syntax
      Use metadata["key"] to retrieve the raw object.
      You can cast it manually if needed.

  • The following index definition indexes content from the @last-modified and @counters metadata properties.

class Products_ByMetadata_AccessViaValue_IndexEntry
{
    public ?DateTime $lastModified = null;
    public function getLastModified(): ?DateTime
    {
        return $this->lastModified;
    }
    public function setLastModified(?DateTime $lastModified): void
    {
        $this->lastModified = $lastModified;
    }

    public ?bool $hasCounters = null;
    public function getHasCounters(): ?bool
    {
        return $this->hasCounters;
    }
    public function setHasCounters(?bool $hasCounters): void
    {
        $this->hasCounters = $hasCounters;
    }
}

class Products_ByMetadata_AccessViaValue extends AbstractIndexCreationTask
{
    public function __construct()
    {
        parent::__construct();

        $this->map = "from product in docs.Products\n" .
                     "let metadata = MetadataFor(product)\n" .
                     "select new { " .
                     "    lastModified = metadata.Value<DateTime>(\"@last-modified\"), " .
                     "    hasCounters = metadata.Value<object>(\"@counters\") != null " .
                     "}";
    }
}
class Products_ByMetadata_AccessViaIndexer_IndexEntry
{
    public ?DateTime $lastModified = null;
    public function getLastModified(): ?DateTime
    {
        return $this->lastModified;
    }
    public function setLastModified(?DateTime $lastModified): void
    {
        $this->lastModified = $lastModified;
    }

    public ?bool $hasCounters = null;
    public function getHasCounters(): ?bool
    {
        return $this->hasCounters;
    }
    public function setHasCounters(?bool $hasCounters): void
    {
        $this->hasCounters = $hasCounters;
    }
}

class Products_ByMetadata_AccessViaIndexer extends AbstractIndexCreationTask
{
    public function __construct()
    {
        parent::__construct();

        $this->map = "from product in docs.Products " .
                     "let metadata = MetadataFor(product) " .
                     "select new {\n" .
                     "    lastModified = (DateTime)metadata[\"@last-modified\"],\n" .
                     "    hasCounters = metadata[\"@counters\"] != null }";
    }
}
  • Query for documents based on metadata values:
    Retrieve documents that have counters and order them by their last modified timestamp.

$results = $session
    ->query(
            Products_ByMetadata_AccessViaValue_IndexEntry::class,
            Products_ByMetadata_AccessViaValue::class
        )
    ->whereEquals("hasCounters", true)
    ->orderByDescending("lastModified")
    ->ofType(Product::class)
    ->toList();
from index "Products/ByMetadata/AccessViaValue"
where hasCounters == true
order by lastModified desc

Metadata properties that can be indexed

  • The following are the predefined metadata properties that can be indexed:

    • @archive-at
    • @attachments
    • @change-vector
    • @collection
    • @counters
    • @etag
    • @expires
    • @id
    • @last-modified
    • @refresh
    • @timeseries
    • Raven-Clr-Type
  • You can add custom metadata properties to any document as needed.
    These custom properties can be indexed just like the predefined ones.


Note:

  • The @attachments metadata property can only be indexed using a Lucene index.
  • The Corax search engine does not support indexing complex JSON properties.
    Learn more in Corax: Handling complex JSON objects.