Author image Marvin Humphrey
and 1 contributors


KinoSearch::Schema -- User-created specification for an inverted index.


First, create a subclass of KinoSearch::Schema which describes the structure of your inverted index.

    package MySchema;
    use base qw( KinoSearch::Schema );
    use KinoSearch::Analysis::PolyAnalyzer;

    our %FIELDS = (
        title   => 'KinoSearch::Schema::FieldSpec',
        content => 'KinoSearch::Schema::FieldSpec',

    sub analyzer { 
        return KinoSearch::Analysis::PolyAnalyzer->new( language => 'en' );

Use the subclass in an indexing script...

    use MySchema;
    my $invindexer = KinoSearch::InvIndexer->new( 
        invindex => MySchema->clobber('/path/to/invindex'),

Use it again at search-time...

    use MySchema;
    my $searcher = KinoSearch::Searcher->new( 
        invindex => MySchema->open('/path/to/invindex')


A Schema is a blueprint specifying how other entities should interpret the raw data in an invindex and interact with it. It's akin to an SQL table definition, but implemented using only Perl code.


KinoSearch::Schema is an abstract class. To use it, you must provide your own subclass.

Every Schema subclass must meet two requirements: it must declare a %FIELDS hash, and it must provide an implementation of analyzer().

Always use the same Schema

The same Schema must always be used with any given invindex. If you tell an InvIndexer to build an invindex using a given Schema, then lie about what the InvIndexer did by supplying your Searcher with either a modified version or a completely different Schema, you'll either get incorrect results or a crash.

Once an actual index has been created using a particular Schema, existing fields may not be associated with new FieldSpec subclasses and their definitions may not be changed. However, it is possible to add new fields during subsequent indexing sessions.



Every Schema subclass must declare a %FIELDS hash using our (not my). The keys of the hash are field names, and the values must be class names which identify either KinoSearch::Schema::FieldSpec or a subclass.

    package UnAnalyzedField;
    use base qw( KinoSearch::Schema::FieldSpec );
    sub analyzed { 0 }

    package MySchema;
    use base qw( KinoSearch::Schema );

    our %FIELDS = (
        title   => 'KinoSearch::Schema::FieldSpec',
        content => 'KinoSearch::Schema::FieldSpec',
        url     => 'UnAnalyzedField',

new() uses %FIELDS as a base set when initializing each new object. Additional fields may be be added subsequently to individual objects using add_field().



    sub analyzer {
        return KinoSearch::Analysis::PolyAnalyzer->new( language => 'en' );

Abstract method. Implementations must return an object which isa KinoSearch::Analysis::Analyzer, which will be used to parse and process field content. Individual fields can override this default by providing their own analyzer().


    sub similarity { KinoSearch::Contrib::LongFieldSim->new }

By default, returns a KinoSearch::Search::Similarity object. If you wish to change scoring behavior by supplying your own subclass of Similarity, override this method.



    my $schema = MySchema->new;
    my $folder = KinoSearch::RAMFolder->new;
    my $invindex = KinoSearch::InvIndex->create(
        schema => $schema,
        folder => $folder,

new() returns an instance of your schema subclass.

Most of the time, you won't need to call new() explicitly, as it is called internally by the factory methods described below.


A Schema is just a blueprint, so it's not very useful on its own. What you need is an InvIndex built according to your Schema, whose content you can manipulate and search.

These three factory methods return an InvIndex object representing an index on your file system at the filepath you specify.


    my $invindex = MySchema->create('/path/to/invindex');

Create a directory and initialize a new invindex at the specified location. Fails if the directory already exists and contains files.


    my $invindex = MySchema->clobber('/path/to/invindex');

Similar to create, but if the specified directory already exists, first attempts to delete any files within it that look like index files.


    my $invindex = MySchema->open('/path/to/invindex');

Open an existing invindex for either reading or updating. All fields which have ever been defined for this invindex will be loaded/verified via add_field().



    $schema->add_field( foo => 'KinoSearch::Analysis::FieldSpec' );

Add a field to an individual schema object.

Calling add_field multiple times against the same field name is fine, but the name of the FieldSpec subclass must always be the same or an exception will be thrown.


Copyright 2007 Marvin Humphrey


See KinoSearch version 0.20.