Tire :include_in_all => false but fields are still included in _all - ruby

I'm using tire for implementing search for a rails app.
The app is backed by CouchDB & couchrest_model gem, which implements ActiveModel.
From the readme it would seen that there's an option :include_in_all it's not explained as to it's behaviour but I'd presume the index would not be included when querying _all
Given the following mapping
mapping do
indexes :id, :index => 'not_analyzed', :include_in_all => false
indexes :title, :analyzer => 'snowball', :boost => 100
indexes :question_content, :analyzer => 'snowball'
indexes :skill_id, :index => 'not_analyzed', :include_in_all => false
indexes :topic_id, :index => 'not_analyzed', :include_in_all => false
indexes :archived, :type => 'boolean', :include_in_all => false
indexes :created_at, :type => 'date', :index => 'not_analyzed', :include_in_all => false
indexes :published_at, :type => 'date', :index => 'not_analyzed', :include_in_all => false
end
I'd expect ES to only search indexes for title and question_content when not specifying a default_field in a query.
Am I miss understanding or is this a bug?
//edit
deleting the index and re-creating it recognises the include_in_all options i've set.

Deleting the index and re-creating it recognises the include_in_all options i've set.

Related

Fedex Ruby Gem: Customs Value is required - how to add?

I'm working with the Ruby gem 'FedEx', https://github.com/jazminschroeder/fedex.
I've set up my code for a development mode and I'm testing making a shipment.
However, I get stuck with the following error:
C:/Ruby22/lib/ruby/gems/2.2.0/gems/fedex-.10.1/lib/fedex/request/shipment.rb:134:in 'failure_response': Customs Value is required. (Fedex:: RateError) from C: /Ruby22/lib/ruby/gems/2.2.0/gems/fedex-.10.1/lib/fedex/request/shipment.rb:32:in 'process_request' from C: /Ruby22/lib/ruby/gems/2.2.0/gems/fedex-3.10.1/lib/fedex/shipment.rb:57:in 'ship' from C: /Ruby22/bin/css_fedex_v1.rb:92:in ''
It seems that I need to parse a 'Customs Value', probably as part of my 'packages' hash. However, I'm unable to find the relevant field for me to enter this in. Anyone who's experienced this and found a solution?
My code is as below:
require 'fedex'
fedex = Fedex::Shipment.new(:key => '***',
:password => '***',
:account_number => '***',
:meter => '***',
:mode => 'development')
shipper = { :name => "***",
:company => "***",
:phone_number => "***",
:address => "***",
:city => "***",
:postal_code => "***",
:country_code => "DK" }
recipient = { :name => "***",
:company => "***",
:phone_number => "***",
:address => "***",
:city => "***",
:postal_code => "***",
:country_code => "GB",
:residential => "false" }
packages = []
packages << {:weight => {:units => "LB", :value => 1}}
shipping_options = {:packaging_type => "YOUR_PACKAGING",
:drop_off_type => "REGULAR_PICKUP"}
rate = fedex.rate(:shipper=>shipper,
:recipient => recipient,
:packages => packages,
:shipping_options => shipping_options)
ship = fedex.ship(:shipper=>shipper,
:recipient => recipient,
:packages => packages,
:service_type => "INTERNATIONAL_PRIORITY",
:shipping_options => shipping_options)
puts ship[:completed_shipment_detail][:operational_detail][:transit_time]
Customs value is declared in their docs:
https://github.com/jazminschroeder/fedex/commit/9f1d4c67b829aaa4eeba9090c1a45d3bd507aab3#diff-4f122efb7c0d98120d8b7f0cd00998e4R106
customs_value = { :currency => "USD",
:amount => "200" }
As I understand you can pass it into the commodities hash or keep it separate.

ruby-aws Amazon Mechanical Turk

I am trying to create a HIT with a pre-created form using the ruby-aws gem and keep getting a missing params error. I have limited the missing params to the params specific to my form.
It seems my request is not being formatted correctly and there are next to no examples from Amazon. My logs say the the following params are missing:
relationship, price, environmental_consciousness, age, occasion, gender, humor, experience, local, romance, additional_information
Any help is much appreciated!
Below is my current request:
hit = mturk.createHIT(
:Operation => 'CreateHIT',
:Title => 'Find a gift based on user scores',
:Description => 'Find a gift for an individual based on survey scores.',
:MaxAssignments => 3,
:Signature => signature,
:Timestamp => timestamp,
:Reward => { :Amount => 0.25, :CurrencyCode => 'USD' },
:HITLayoutId => '3AV6FF2M2GYMGLRQEKHZ7EBN4EZOJE',
:HitLayoutParameter => {'Name' => 'additional_information', 'Value' => 'TEST'},
:HitLayoutParameter => {'Name' => 'age', 'Value' => '22'},
:HitLayoutParameter => {'Name' => 'environmental_consciousness', 'Value' => '54'},
:HitLayoutParameter => {'Name' => 'experience', 'Value' => '32'},
:HitLayoutParameter => {'Name' => 'gender', 'Value' => 'male'},
:HitLayoutParameter => {'Name' => 'humor', 'Value' => '66'},
:HitLayoutParameter => {'Name' => 'local', 'Value' => '21'},
:HitLayoutParameter => {'Name' => 'occasion', 'Value' => '43'},
:HitLayoutParameter => {'Name' => 'price', 'Value' => '33'},
:HitLayoutParameter => {'Name' => 'relationship', 'Value' => '23'},
:HitLayoutParameter => {'Name' => 'romance', 'Value' => '23'},
:Keywords => 'data collection, gifting, gifts, shopping, gift listings, presents',
:AssignmentDurationInSeconds => 300,
:LifetimeInSeconds => 604800
)
I was able to resolive the issue - AWS has terrible naming conventions. The above example does use the correct format, however HitLayoutParameter must be HITLayoutParameter - Notice the CAPITAL HIT vs Hit.
Also, when submitting multiple parameters, the should only be one HITLayoutParameter that equals an array of Name/Value pairs. Working code below.
Hope this helps someone else!
Best,
~DFO~
hit = mturk.createHIT(
:Operation => 'CreateHIT',
:Title => 'Find a gift based on user scores',
:Description => 'Find a gift for an individual based on survey scores.',
:MaxAssignments => 3,
:Signature => signature,
:Timestamp => timestamp,
:Reward => { :Amount => 0.25, :CurrencyCode => 'USD' },
:HITLayoutId => '3AV6FF2M2GYMGLRQEKHZ7EBN4EZOJE',
:HITLayoutParameter => [
{:Name => 'additional_information', :Value => 'TEST'},
{:Name => 'age', :Value => '22'},
{:Name => 'environmental_consciousness', :Value => '54'},
{:Name => 'experience', :Value => '32'},
{:Name => 'gender', :Value => 'male'},
{:Name => 'humor', :Value => '66'},
{:Name => 'local', :Value => '21'},
{:Name => 'occasion', :Value => '43'},
{:Name => 'price', :Value => '33'},
{:Name => 'relationship', :Value => '23'},
{:Name => 'romance', :Value => '23'}
],
:Keywords => 'data collection, gifting, gifts, shopping, gift listings, presents',
:AssignmentDurationInSeconds => 300,
:LifetimeInSeconds => 604800
)

How to count values in a array of hashes

I have an array of hashes
[ {:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},....
{:name => "Will", :type => "none", :product => "oranges"} ]
and was wondering if there is a simple way to count the number of product's and store the count as well as the value in an array or hash.
I want the result to be something like:
#products = [{"apples" => 2, "oranges => 1", ...}]
You can do as
array = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
array.each_with_object(Hash.new(0)) { |h1, h2| h2[h1[:product]] += 1 }
# => {"apples"=>2, "oranges"=>1}
You can use Enumerable#group_by and Enumerable#map
array.group_by{|h| h[:product]}.map{|k,v| [k, v.size]}.to_h
# => {"apples"=>2, "oranges"=>1}
While not exactly what the OP was looking for, this may be helpful to many. If you're just looking for the count of a specific product, you could do this:
array = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
array.count { |h| h[:product] == 'apples' }
# => 2
You could count:
hashes = [
{:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"}
]
hashes.inject(Hash.new(0)) { |h,o| h[o[:product]] += 1; h }
Or maybe...
hashes.instance_eval { Hash[keys.map { |k| [k,count(k)] }] }
I do not know which is the more performant, the latter seims weird to read though.
I would do:
items =[ {:name => "bob", :type => "some", :product => "apples"},
{:name => "ted", :type => "other", :product => "apples"},
{:name => "Will", :type => "none", :product => "oranges"} ]
counts = items.group_by{|x|x[:product]}.map{|x,y|[x,y.count]}
p counts #=> [["apples", 2], ["oranges", 1]]
Then if you need it as a Hash just do:
Hash[counts]

How to make multiple file uploading via CarrierWave and Sinatra?

I'm not first who is asking and maybe not last. How to implement multiple uploading with CarrierWave in Sinatra? I'm using this code in action:
post '/create' do
params.delete 'submit'
d = Dcmnt.new(
:published => params[:published],
:name => params[:name],
:description => params[:description],
:created_at => Time.now
)
d.attachment = params[:attachments]
d.save
redirect '/success'
end
With this model:
class Dcmnt
include Mongoid::Document
store_in collection: 'dcmnts'
field :published, type: Boolean
field :name, type: String
field :description, type: String
field :created_at, type: Date
mount_uploader :attachment, Uploader, type: String
end
And this form:
%form{:method => "post", :action => "/create", :enctype => "multipart/form-data"}
%input{:type => "checkbox", :name => "published", :value => "true"} Published?
%input{:name => "name"}
%textarea{:name => "description", :rows => "5"}
%div.form-group
%label Attachments
%input{:type => "file", :name => "attachments[]"}
%input{:type => "file", :name => "attachments[]"}
%input{:type => "file", :name => "attachments[]"}
%input{:type => "file", :name => "attachments[]"}
%input{:type => "file", :name => "attachments[]"}
Also CW's configuration:
class Uploader < CarrierWave::Uploader::Base
storage :file
def store_dir
'attachments/' + model.id
end
end
Looks correct, but doesn't work. When I'm trying to upload couple of files either single file, Pow returns me no implicit conversion of nil into String on d.attachment = params[:attachments] line. And I can't figure out why. Can you help me with this?

Elastic Search Multiple Fields

I'm using Tire to index and search a database of cars:
create :mappings => {
:cars => {
:properties => {
:id => {:type => 'string', :index => 'not_analyzed', :include_in_all => true},
:user_id => {:type => 'string', :index => 'not_analyzed'},
:name => {:type => 'string', :analyzer => 'snowball' },
:time => {:type => 'long', :index => 'not_analyzed'},
:origin_country => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
:origin_state => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
:origin_city => {:type => 'string', :analyzer => 'keyword', :include_in_all => false},
:dealer_name => {:type => 'string', :analyzer => 'snowball', :boost => 1.5, :include_in_all => false}
}
}
}
And queries look like:
s = Tire.search Search.index_name do
query do |query|
query.text :_all, downcased_query, :type => :phrase
end
end
Right now if you search for "New York Joe Dealer" it will match if there is a dealer_name is "Joe Dealer" or if the origin_state is "New York" but not both. Is there a way to match origin_state is "New York" and "dealer_name" is "Joe Dealer" (or either)? The idea is I want a user to enter in a fre-form query string and be able to find the best matches possible and to a user they would expect to enter New York Joe Dealer and find all cars sold at Joe Dealer in New York (or all cars in New York or at Joe Dealer ranked lower).
The correct solution would be to use the multi_match query to perform the same query against multiple fields. It's supported in Tire, see https://github.com/karmi/tire/blob/master/test/integration/match_query_test.rb.
Tire.search Search.index_name do
query do |query|
query.match :dealer_name, downcased_query
query.match :origin_state, downcased_query
end
end
You can even use the phrase type if the query would contain both the dealer and state info in correct order, such as "New York Joe Dealer".
The solution was to move to a "match" type filter, and diable :type => :phrase, so:
query do |query|
query.match :_all, downcased_query
end
There are still some issues with sorting so that time is still a big input, but this resolves many of the issues.

Resources