Elasticsearch autocomplete with picture of product and other options - ruby-on-rails

Recently I've started to learn elasticsearch and currently working with some sample product data. Now I want to suggest the product as user type it. I've checked some documentations for Completion Suggester and implemented some examples for completion.
I checked some benefits of using _suggest than normal _search like
SPEED
Real Time
Readability
Custom Ordering
Here is the script I tried:
`POST /products/_suggest
{
"product" : {
"text" : "fres",
"completion" : {
"field" : "name"
}
}
}`
But now, I want to implement suggester that will suggest as user type with the picture of product and some other options with product name like Add to cart etc
I am implementing all this with the help of elasticsearch-rails gem over ruby on rails.
So can I do it with normal completion type as it provides lots of feature over search or else normal search will be good for this scenario?

Elastic Search (ES) allows things that "normal search" won't: extended full text search end especially fuzzy search (a typo like 'hoem' can return 'home' anyway...).
But an ES query returns only data that is indexed in ES !
You will probably not index your pictures so you'll have to process the ES answer and generate a 'pretty' suggest listing with pictures (ES will return entries with both ES and ActiveRecord IDs)
Feel free to ask if you need more details

Related

Searching in polygons in sphinx using Thinking Sphinx

I have setup thinking sphinx for real-time indexing and It works very well and search with geodist as well.But now I want to search the records within polygon.
Sphinx documentation explains it very well at Geo-distance searching
now I want to use this functionality using thinking sphinx.
Thinking sphinx does explain about geodist search Here
But It does not state how to search within a polygon.
Can any one help me here to do that?
Thinking Sphinx doesn't have anything inbuilt to provide a neat interface for the polygon searching, but it's certainly possible to use the functionality.
You'll want to generate the SphinxQL SELECT clause that you'd like, filter on it accordingly, and/or you can access your custom attributes using the AttributesPane. The following code is hopefully clear:
search = Model.search("foo",
:select => "*, CONTAINS(GEOPOLY2D(...), ...) AS inside",
:with => {:inside => true}
); ""
search.context[:panes] << ThinkingSphinx::Panes::AttributesPane
search.collect { |instance| instance.sphinx_attributes["inside"] }
The ; "" at the end of the first statement is only needed when running this in IRB or a Rails console - you want to avoid calling search in a way that evaluates the results until you've added the pane in. Search results are normally lazily loaded, but IRB calls inspect to print statement results which removes the lazy advantage.
Panes are discussed in a blog post I wrote, and the source code for the AttributesPane class is very simple. You may also want to write a custom middleware class that uses your own options and translates them into the polygon functions - the Geographer class (which is what translates :geo into GEODIST) is a good reference for that.

EmberJS 2.7, Rails 5, AMS 0.10.2 - GET resources collection where fieldX=[B or C]

I have an EmberJS filter like this:
/app/routes/trails/new.js
model: function (filterCurrentEmployees) {
return Ember.RSVP.hash({
trail: this.store.createRecord('trail'),
employees: this.store.query('employee', { status: '1,2'}).then(
function(data) {return data})
})
},
I was hoping that status: '1,2' would end up as a normal Rails param so I could do params[:status] and then filter the returned employees (you know so the db would get a query like 'where status IN ['1','2']')
But when this filter query is sent to Rails API I get this error:
ActiveModelSerializers::Adapter::JsonApi::Deserialization::InvalidDocument (Invalid payload ({:data=>"Expected hash"}): {"status"=>"1,2", "controller"=>"employees", "action"=>"index"}):
which occurs here in the controller:
api/app/controllers/employees.rb
def employee_params
ActiveModelSerializers::Deserialization.jsonapi_parse!(params)
end
but that is needed for AMS to work with Ember.
So I presume something is wrong with the way I am sending/creating the query in EmberJS?
It seems to be trying to make a GET collection request. Not sure really and this explains sort-of what is going on at the Rails end, but I don't know how to get Ember to create the filter properly so that AMS is happy to accept it.
EDIT - JSON-API Spec Reference
I was under the impression that AMS and Ember 2.7 with JSON-API 'just work out of the box'. I was actually expecting the Ember filter to comply with the spec and send
/employees?filter=status[1,2]
but it seems to not be doing that. AMS says the same thing here.
UPDATE
So with some pointers from the comments (thank you) I learned that the structure of the query hash might be incorrect. I also tried changing 'query' to filter but that then raises an actual Ember error:
The filter API has been moved to a plugin. To enable store.filter using an environment flag, or to use an alternative, you can visit the ember-data-filter addon page.
Now I don't know what the difference is between an Ember query and an Ember filter, perhaps a filter only runs on the client? Who knows, the docs are so sparse and so many questions on this are 1 or 2 years old.
So after much digging around for Ember Gold Nuggets, I found out that Controllers are STILL needed for...you guessed it...Query Parameters.
I've never used a Controller, and thought I never needed one.
So it seems I was basing my attempt at using query parameters on outdated information and code examples.
For those who run into this, the gold nuggets are here and here.
Also, it seems Javascript Object parameters as per JSON-API spec are not yet supported in Ember, according to this, although it's nearly a year old so do not know if that is still true.
UPDATE
So, after further gold mining, it seems I was confused and that Controllers are needed for Query Parameters in Ember on the client side, to assist the frontend application when it transitions from one route to another (and that is when you need a Controller to set them up).
But I want to just send a query parameter from within the Route code directly to the API, and examples of doing that are very hard to find.
So in the Rails Log I would expect to see BEFORE deserialization by ASM:
Rails.logger.info "Params are: #{params.to_json}"
something like this:
Params are:
{"data":{"filter":{"status["1,2"]}},
"controller":"employees","action":"index"}
ASM expects 'data' to be the root element of the hash, and then inside that I can place my filter. For example, from the Ember Route:
model: function () {
let myFilter = {};
myFilter.data = { filter: {status: ['1,2']}};
return Ember.RSVP.hash({
trail: this.store.createRecord('trail'),
employees: this.store.query('employee', myFilter).then(function(data) {return data})
})
},

Ruby on Rails filterrific gem simple filter

I'm new to Ruby on Rails and currently trying to set up an easy search with filterrific. But all examples I can find are much more complicated then mine and I'm a bit confused:
I have a model where I store Bank Holidays. I want to filter the output so the user just sees one year, should default to current year.
Therefore I created a scope in my model:
selected_year = Date.today.year
scope :year, -> {
where("YEAR(holiday_date) = #{selected_year}")
}
All examples for filterrific have found exspect that a user wants to search matching different values in related databases.
Any hint on how to filter just simple one value?
Thanks
Simon
It looks like you want to allow the scope to receive an argument like so
scope :year, ->(year) { where("YEAR(holiday_date) = #{year}") }
Then you can call Model.year(1986) etc.

Notifications or user activity log implementation

The application has certain actions that are recorded for each user and recorded in db table notifications. The table has the following structure:
user_id, notification_type, credit, timestamp
notification_type does not store the entire text of the notification but just stores a short type description.
Later when the user wants to view his notifications I use a helper method from my view to fetch the actual text.
def notification_text(type)
case type_id
when 'flagPositive'
return 'A question you flagged has been marked as correct.'
when 'qAccepted'
return 'A question you added has been accepted.'
when 'qModerated'
return 'You moderated a question.'
when 'flagReport'
return 'You moderated a flag.'
end
end
1) Is this an optimum way to do this?
2) Should I replace the type_description with integer values (say 1 -> flagPositive, 2-> qAccepted) for performance benefits?
3) Are there any best practices around the same that I should be following?
1) This highly depends on your application and requirements. What I can say is that I used this approach sometimes and faced no problems so far.
2) If you see a performance problem with the string lookup, you could do so. A general recommendation is to optimize performance only when really needed.
3) Just google for "Ruby", "Rails", "ActiveRecord" and "Enum". You'll find lots of discussions about different solutions for this kind of problem. There are similar questions on this site, e.g., Enums in Ruby or In Rails, how should I implement a Status field for a Tasks app - integer or enum?

break down a complex search query in Rails 3

I have a controller which has a lot of options being sent to it via a form and I'm wondering how best to separate them out as they are not all being used simultaneously. Ie sometimes no, tags, sometimes no price specified. For prices I have a default price set so I can work around with it always being there, but the tags either need to be there, or not. etc.
#locations = Location.find(params[:id])
#location = #locations.places.active.where("cache_price BETWEEN ? AND ?",price_low,price_high).tagged_with([params[:tags]).order(params[:sort]).paginate :page => params[:page]
I haven't seen any good examples of this, but I'm sure it must happen often... any suggestions? Also, even will_paginate which gets tacked on last should be optional as the results either go to a list or to a google map, and the map needs no pagination.
the first thing to do when refactoring a complex search action is to use an anonymous scope.
Ie :
fruits = Fruit.scoped
fruits = fruits.where(:colour => 'red') if options[:red_only]
fruits = fruits.where(:size => 'big') if options[:big_only]
fruits = fruits.limit(10) if options[:only_first]
...
If the action controller still remains too big, you may use a class to handle the search. Moreover, by using a class with Rails 3 and ActiveModel you'll also be able to use validations if you want...
Take a look at one of my plugins : http://github.com/novagile/basic_active_model that allows you to easily create classes that may be used in forms.
Also take a look at http://github.com/novagile/scoped-search another plugin more specialized in creating search objects by using the scopes of a model.

Resources