Skip to content

[FIX] Fix search with type specified in the class #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 27 commits into from

Conversation

pepe
Copy link
Contributor

@pepe pepe commented Apr 15, 2014

When type was set in the custom repository class, it was not respected, when searching, only when finding.

Please can you advice me how to add test for this?

karmi and others added 27 commits April 9, 2014 20:51
Instead of:

    class MyRepository
      include Elasticsearch::Persistence::Repository
    end

    repository = MyRepository.new

you can do:

    repository = Elasticsearch::Persistence::Repository.new

The module function `new` returns an Elasticsearch::Persistence::Repository::Class instance.
Provides getting Ruby class from Elasticsearch type and vice versa,
ID from the document (Hash), as well as setting the `klass`
for the whole Repository instance.
The repository uses two symmetric methods: `serialize` and `deserialize`
to convert documents when:

1. passing them to the storage,
2. initializing Ruby objects when retrieving documents from storage

Every repository can easily customize (overload) these methods,
to provide (de)serialization for complex use-cases, such as storing
PDF files or images in the storage.

See:

* https://www.braintreepayments.com/braintrust/untangle-domain-and-persistence-logic-with-curator
* https://github.com/braintree/curator/blob/master/lib/curator/repository.rb
The `Store` module saves and deletes the documents in Elasticsearch
via the `save` and `delete` methods.
The module provides method to find one or multiple documents and to
check for documents existence.

The methods return `deserialize`-d Ruby objects based on `klass` or
the document Elasticsearch `_type`.

Missing documents are kept in the resulting Array as `nil` objects.
The module provides an interface for getting objects from the repository
based on a search query.

The results are wrapped in the `Response::Results` instance, which
proxies methods to the `results` property.
So:

    reposistory.klass = Foobar

is equivalent to:

    repository.klass Foobar
Included `Elasticsearch::Model::Indexing::ClassMethods` to support setting the index name and document type,
and to allow configuring the mappings and settings for the index.

See:

https://github.com/elasticsearch/elasticsearch-rails/blob/6f4a57a/elasticsearch-model/lib/elasticsearch/model/indexing.rb
…ository

Also available as `document_type="foo"`.
… it's set

When the `document_type` is configured for the repository, it is used
in `save`, `delete`, `find`, etc method to set the `type` parameter
for the client.

When the `document_type` is not set, the old behaviour of inferring
from `klass`, `document.class`, etc. is preserved.
To provide flexibility to the end-user, the integration of the "Repository" module
has been refactored to proxy all repository methods via a gateway.

This allows users to set up the repository in a custom class, with class methods, in a DSL-like fashion:

    class NoteRepository
      include Elasticsearch::Persistence::Repository

      klass Note
      index :my_notes

      mapping do
        indexes :title, analyzer: 'snowball'
      end

      client.transport.logger = Logger.new(STDERR)

      gateway do
        def serialize(document)
          super.merge(special: 'stuff')
        end
      end
    end

The bundled Repository class can be configured via a block passed to the initializer:

    repository = Elasticsearch::Persistence::Repository.new do
      klass Note
      index :my_notes

      mapping do
        indexes :title, analyzer: 'snowball'
      end

      client.transport.logger = Logger.new(STDERR)
    end

The repository methods can be accessed via the class or instance methods:

    NoteRepository.klass Note
    repository.klass Note
    class NoteRepository
      include Elasticsearch::Persistence::Repository
    end

    NoteRepository.index_name
    => "note_repository"
Also, when using the "shortcut" to create the repository, a default
name of `repository` is set.
Both:

    repository.client = MyClient.new

and:

    repository.client MyClient.new

are equivalent now.
…ds directly in the class

Instead of calling the `gateway` method with a block, to redefine the serialize/deserialize methods:

    class NoteRepository
      gateway do
        def serialize(document)
          Hash[document.to_hash.map() { |k,v|  v.upcase! if k == :title; [k,v] }]
        end
        def deserialize(document)
          MyNote.new ActiveSupport::HashWithIndifferentAccess.new(document['_source']).deep_symbolize_keys
        end
      end
    end

Define them directly in the class, and they will be intercepted by the hook, and (re)defined directly on the gateway:

    class NoteRepository
      def serialize(document)
        Hash[document.to_hash.map() { |k,v|  v.upcase! if k == :title; [k,v] }]
      end
      def deserialize(document)
        MyNote.new ActiveSupport::HashWithIndifferentAccess.new(document['_source']).deep_symbolize_keys
      end
    end

See: http://www.ruby-doc.org/core-2.1.1/Module.html#method-i-method_added

(COMITTED WITH FINGERS CROSSED :)
@karmi
Copy link
Contributor

karmi commented Apr 17, 2014

Thanks!, merged in 8d6473e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants