我在轨道4应用中使用轮胎和mongoid。
class Agent
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Taggable
include Tire::Model::Search
include Tire::Model::Callbacks
...
mapping do
indexes :id, index: :not_analyzed
indexes :name, type: 'string', analyzer: 'pattern'
indexes :tags_array, type: 'string', analyzer: 'pattern'
end
...
def self.search(params)
tire.search(load: true) do
query do
string "name:#{params}"
string "tags_array:#{params}"
end
end
end
...
有4个代理
Agent.all.collect(&:tags)
=> ["pune", "pune", "press", "pune press"]
Agent.all.collect(&:name)
=> ["agent smith", "first", "second", "third"]
我有3个问题
1)第一个问题是代理商无法通过“名称”进行搜索。
results = Agent.search('first')
=> #<Tire::Results::Collection:0xb26dc4c @response={"took"=>1, "timed_out"=>false, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}, "hits"=>{"total"=>0, "max_score"=>nil, "hits"=>[]}}, @options={:load=>true, :size=>10}, @time=1, @total=0, @facets=nil, @max_score=0.0, @wrapper=Tire::Results::Item>
results.results
=> []
2)第二个问题是mongoid给出了指定具有指定id的对象不存在的错误。如果我基于标签搜索
results = Agent.search('press')
=> #<Tire::Results::Collection:0xb296da4 @response={"took"=>1, "timed_out"=>false, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}, "hits"=>{"total"=>2, "max_score"=>0.30685282, "hits"=>[{"_index"=>"agents", "_type"=>"agent", "_id"=>"{\"$oid\"=>\"521da715f94adc957d000005\"}", "_score"=>0.30685282, "_source"=>{"name"=>"second", "tags_array"=>["press"]}}, {"_index"=>"agents", "_type"=>"agent", "_id"=>"{\"$oid\"=>\"521da715f94adc957d000004\"}", "_score"=>0.19178301, "_source"=>{"name"=>"third", "tags_array"=>["pune press"]}}]}}, @options={:load=>true, :size=>10}, @time=1, @total=2, @facets=nil, @max_score=0.30685282, @wrapper=Tire::Results::Item>
results.results
Mongoid::Errors::DocumentNotFound:
Problem:
Document(s) not found for class Agent with id(s) {"$oid"=>"521da715f94adc957d000005"}, {"$oid"=>"521da715f94adc957d000004"}.
Summary:
When calling Agent.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): {"$oid"=>"521da715f94adc957d000005"}, {"$oid"=>"521da715f94adc957d000004"} ... (2 total) and the following ids were not found: {"$oid"=>"521da715f94adc957d000005"}, {"$oid"=>"521da715f94adc957d000004"}.
Agent.all.collect(&:id)
=> ["521da715f94adc957d000007", "521da715f94adc957d000006", "521da715f94adc957d000005", "521da715f94adc957d000004"]
3)如果我重新索引Agent对象,弹性搜索中的id与mongodb对象id完全不同
Agent.index_name
=> "agents"
Tire.index('agents').delete
=> true
Agent.import
=> #<Tire::Model::Import::Strategy::Mongoid:0xb2dad9c @klass=Agent, @options={:per_page=>1000}, @index=#<Tire::Index:0xb2dabe4 @name="agents", @response=#<Tire::HTTP::Response:0xb30c4b4 @body="{\"took\":630,\"items\":[{\"create\":{\"_index\":\"agents\",\"_type\":\"agent\",\"_id\":\"h0k78SupT9GGTT3I6qV3Bw\",\"_version\":1,\"ok\":true}},{\"create\":{\"_index\":\"agents\",\"_type\":\"agent\",\"_id\":\"LuJMwJSFRquezRUc1HUpEg\",\"_version\":1,\"ok\":true}},{\"create\":{\"_index\":\"agents\",\"_type\":\"agent\",\"_id\":\"gE6MreF8T4ePdD8lqutSJQ\",\"_version\":1,\"ok\":true}},{\"create\":{\"_index\":\"agents\",\"_type\":\"agent\",\"_id\":\"4azbinLjSO2LuRXn9-WYtg\",\"_version\":1,\"ok\":true}}]}", @code=200, @headers={:content_type=>"application/json; charset=UTF-8", :content_length=>"426"}>>>
results = Agent.search('press')
=> #<Tire::Results::Collection:0xb31bcac @response={"took"=>5, "timed_out"=>false, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}, "hits"=>{"total"=>2, "max_score"=>1.0, "hits"=>[{"_index"=>"agents", "_type"=>"agent", "_id"=>"gE6MreF8T4ePdD8lqutSJQ", "_score"=>1.0, "_source"=>{"name"=>"second", "tags_array"=>["press"]}}, {"_index"=>"agents", "_type"=>"agent", "_id"=>"4azbinLjSO2LuRXn9-WYtg", "_score"=>0.19178301, "_source"=>{"name"=>"third", "tags_array"=>["pune press"]}}]}}, @options={:load=>true, :size=>10}, @time=5, @total=2, @facets=nil, @max_score=1.0, @wrapper=Tire::Results::Item>
results.results
=>Mongoid::Errors::DocumentNotFound:
Problem:
Document(s) not found for class Agent with id(s) gE6MreF8T4ePdD8lqutSJQ, 4azbinLjSO2LuRXn9-WYtg.
我是否正确定义了映射?用户应该能够根据代理名称或/和标签进行搜索。也应该允许部分名称。
== UPDATE
作为localhost的结果,来自elasticsearch的映射:9200 / _mapping?pretty = 1"agents" : {
"agent" : {
"properties" : {
"id" : {
"type" : "string",
"index" : "not_analyzed",
"omit_norms" : true,
"index_options" : "docs"
},
"name" : {
"type" : "string"
},
"tags_array" : {
"type" : "string"
}
}
}
}
答案 0 :(得分:0)
过去两天我一直在寻找上述问题的解决方案。最后,在https://github.com/karmi/tire/issues/775找到了解决方案。
问题及解决方案的说明
> Agent.all.collect(&:name)
=> ["first", "second", "third", "agent smith"]
> Agent.all.collect(&:id)
=> ["52204be3f94adc86b2000007", "52204be3f94adc86b2000006", "52204be3f94adc86b2000005", "52204be3f94adc86b2000004"]
> Agent.all.collect(&:tags)
=> ["press pune", "press", "pune", "matrix"]
$ a = Agent.search('pu')
=> #<Tire::Results::Collection:0xbb24cf0 @response={"took"=>1, "timed_out"=>false, "_shards"=>{"total"=>5, "successful"=>5, "failed"=>0}, "hits"=>{"total"=>2, "max_score"=>0.5, "hits"=>[{"_index"=>"agents", "_type"=>"agent", "_id"=>"{\"$oid\"=>\"52204be3f94adc86b2000005\"}", "_score"=>0.5, "_source"=>{"name"=>"third", "tags_array"=>["pune"]}}, {"_index"=>"agents", "_type"=>"agent", "_id"=>"{\"$oid\"=>\"52204be3f94adc86b2000007\"}", "_score"=>0.5, "_source"=>{"name"=>"first", "tags_array"=>["press pune"]}}]}}, @options={:load=>true, :size=>10}, @time=1, @total=2, @facets=nil, @max_score=0.5, @wrapper=Tire::Results::Item>
2 results present for the above search.
$ a.results
=>
Mongoid::Errors::DocumentNotFound:
Problem:
Document(s) not found for class Agent with id(s) {"$oid"=>"52204be3f94adc86b2000005"}, {"$oid"=>"52204be3f94adc86b2000007"}.
Summary:
When calling Agent.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): {"$oid"=>"52204be3f94adc86b2000005"}, {"$oid"=>"52204be3f94adc86b2000007"} ... (2 total) and the following ids were not found: {"$oid"=>"52204be3f94adc86b2000005"}, {"$oid"=>"52204be3f94adc86b2000007"}.
Resolution:
Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.
....
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/bundler/gems/mongoid-85e146637503/lib/mongoid/findable.rb:88:in `find'
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/gems/tire-0.6.0/lib/tire/results/collection.rb:156:in `__find_records_by_ids'
....
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/gems/tire-0.6.0/lib/tire/results/collection.rb:144:in `block in __get_results_with_load'
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/gems/tire-0.6.0/lib/tire/results/collection.rb:131:in `each'
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/gems/tire-0.6.0/lib/tire/results/collection.rb:131:in `__get_results_with_load'
from /home/prasad/.rvm/gems/ruby-2.0.0-p247/gems/tire-0.6.0/lib/tire/results/collection.rb:27:in `results'
from (irb):2
# method used in tire to retrieve the objects based on the id(s). id or array of ids.
def __find_records_by_ids(klass, ids)
@options[:load] === true ? klass.find(ids) : klass.find(ids, @options[:load])
end
https://github.com/mongoid/mongoid/blob/master/CHANGELOG.md mongoid 4 changelog指定
#2497 Calling to_json no longer tampers with the return value from the driver, and proper returns{ "$oid" : object_id.to_s } instead of just the string representation previously
Tire期望一组id,但得到一个哈希为ids:{“$ oid”=&gt;“52204be3f94adc86b2000005”},{“$ oid”=&gt;“52204be3f94adc86b2000007”}并试图找到对象为
Agent.find({"$oid"=>"52204be3f94adc86b2000005"}, {"$oid"=>"52204be3f94adc86b2000007"}) #and hence the error.
以下代码有效:
Agent.find("52204be3f94adc86b2000004", "52204be3f94adc86b2000007")
Agent.find(["52204be3f94adc86b2000004", "52204be3f94adc86b2000007"])
Agent.all.collect(&:name).as_json
=> ["first", "second", "third", "agent smith"]
Agent.all.collect(&:id).as_json
=> [{"$oid"=>"52204be3f94adc86b2000007"}, {"$oid"=>"52204be3f94adc86b2000006"}, {"$oid"=>"52204be3f94adc86b2000005"}, {"$oid"=>"52204be3f94adc86b2000004"}]
临时黑客:添加具有以下内容的初始化程序
require "tire"
module Tire
class Index
def get_id_from_document(document) #document is the object. ie agent object in the above case
case
when document.is_a?(Hash)
document[:_id] || document['_id'] || document[:id] || document['id']
#if is not an hash and responds to 'id' and object_id is not equal to id "Agent.last.object_id => 96643940"
when document.respond_to?(:id) && document.id != document.object_id
document.id.to_s # was document.id.as_json
end
end
end
end