mongodb/rails "exception: can't find special index: 2d for:" - ruby-on-rails

i have a rails app where i have some problems with indexes. I search locations by name.
First i thought its a problem with the addresses.coords but iam not sure about it.
The relevant parts of the search controller:
#practices = Practice.published
#practices = #practices.where(:"addresses.country" => params[:country].upcase) if params[:country].present?
if params[:location].present? && latlng = get_coordinates
#practices = #practices.near_sphere(:"addresses.coords" => latlng).max_distance(:"addresses.coords" => get_distance )
end
# now find doctors based on resulting practices
#doctors = Doctor.published.in("organization_relations.practice_id" => #practices.distinct(:_id))
The complete crash log:
Moped::Errors::OperationFailure (The operation: #<Moped::Protocol::Command
#length=255
#request_id=646
#response_to=0
#op_code=2004
#flags=[]
#full_collection_name="um-contacts.$cmd"
#skip=0
#limit=-1
#selector={:distinct=>"practices", :key=>"_id", :query=>{"deleted_at"=>nil, "published_at"=>{"$lte"=>2012-11-05 15:17:14 UTC}, "addresses.country"=>"DE", "addresses.coords"=>{"$nearSphere"=>[13.4060912, 52.519171], "$maxDistance"=>0.01569612305760477}}}
#fields=nil>
failed with error 13038: "exception: can't find special index: 2d for: { deleted_at: null, published_at: { $lte: new Date(1352128634313) }, addresses.country: \"DE\", addresses.coords: { $nearSphere: [ 13.4060912, 52.519171 ], $maxDistance: 0.01569612305760477 } }"
See https://github.com/mongodb/mongo/blob/master/docs/errors.md
for details about this error.):
app/controllers/search_controller.rb:16:in `index'
Thats the result of the indexes, not sure how to query them from the addresses which are embedded via has_many.
> db.practices.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "um-contacts.practices",
"name" : "_id_"
}
]
Help would be really appreciated!
Edit: Looks like the indexes for adresses.coords arent created,
db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.users", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.doctors", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.collaborations", "name" : "_i
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.practices", "name" : "_id_" }
but should be created within the practice class:
class Practice
...
embeds_many :addresses, cascade_callbacks: true, as: :addressable
...
field :name, type: String
field :kind, type: String
field :slug, type: String
index({"addresses.coords" => '2d'}, { min: -180, max: 180, background: true })
index({name: 1})
index({slug: 1}, { unique: true })
...
Anyone have an idea why its failing?

try to re-create your indexes. for mongoid:
rake db:mongoid:create_indexes

Related

firebase database filtering is not working. Need some assistance

I have a simple test database that I cant get to filter. I indexed the category in the rules:
"questions":{
".indexOn": ["category"]
},
My filter for the quiz app:
/questions.json?orderBy="category"&equalTo="Basics"&print=pretty
and my database:
"-MKoucSP33zm4jC43AnY" : {
"title" : {
"answers" : [ {
"score" : 30,
"text" : "Pineapple"
}, {
"score" : 5,
"text" : "Ham"
}, {
"score" : 20,
"text" : "Yogurt"
}, {
"score" : 10,
"text" : "Crab"
} ],
"category" : "Basics",
"questionId" : "101",
"questionImage" : "",
"questionLink" : "",
"questionText" : "What topping do you like the best on pizza?"
}
}
The category property is nested under the title node, so the property you need to order/filter on is title/category:
/questions.json?orderBy="title/category"&equalTo="Basics"&print=pretty
You'll also need to update your index definition for that path, so:
"questions": { ".indexOn": "title/category" }
Working example: https://stackoverflow.firebaseio.com/64596200/questions.json?orderBy="title/category"&equalTo="Basics"

ElasticSearch sorting

ElasticSearch Version: 1.3.2
I am trying to sort simple collection but no matter what I try it just ignore sorting to me...
{
"query":{
"filtered":{
"query":{
"match_all":{
}
},
"filter":{
"bool":{
"must":[
{
"terms":{
"status":[
"active",
"featured"
]
}
}
]
}
}
}
},
"sort":[
{
"price_cents":{
"order":"asc"
}
}
]
}
I've noticed in my mapping I have auto_boost = true
{
"items" : {
"mappings" : {
"item" : {
"dynamic" : "false",
"_all" : {
"auto_boost" : true
},
"properties" : {
"price_cents" : {
"type" : "integer"
},
"status" : {
"type" : "string"
},
"title" : {
"type" : "string",
"boost" : 10.0,
"analyzer" : "snowball"
}
}
}
}
}
}
this attribute has been added automatically by https://github.com/elasticsearch/elasticsearch-rails gem which I use:
mappings :dynamic => false do
indexes :title, :analyzer => 'snowball', :boost => 10.0
indexes :status
indexes :price_cents, :type => :integer, :index => 'not_analyzed'
end
I wonder is the "auto_boost": true the reason of sort ignore? I can't find the correct way how to turn it to false and check...
I found the issue, it is kind of related to the current bug with .records (https://github.com/elasticsearch/elasticsearch-rails/issues/206), because of it does not paginating correctly I used temporary this construction
#paginates_items = Item.search(params).page(params[:page]).per(60).results
item_ids = #paginates_items.collect(&:id)
#items = Item.where(:id => item_ids)
but I forgot that where(:id => items_id) completely break the order...

MongoID : match multiple elements in array and update all

I use MongoID and PostgreSQL on Rails 4 and I have a notification system.
Each user has one notification document. I would like to be able to mark all as read in a controller.
Here is my notification schema :
{
"_id" : ObjectId("53e360156d6163513e000000"),
"unread_counter" : 1,
"user_id" : 1,
"rows" : [
{
"_id" : ObjectId("53e369166d61635328000000"),
"readed" : false,
"created_at" : ISODate("2014-08-07T11:55:02.936Z"),
"author" : {
"_id" : ObjectId("53e369166d61635328010000"),
"username" : "edouard",
"user_id" : 6
},
"subject" : {
"_id" : ObjectId("53e369166d61635328020000"),
"type" : "follower"
}
}
]
}
The problem is that elem_match just match one element in rows array.
Notification.where(:user_id => current_user.id)
.elem_match(rows: { readed: false })
.update_all("$set" => {"rows.$.readed" => true })
I have been inspired by this post : mongoid update elements within array
How can I match all "readed" : false row elements and then update them to true ?

MVC KENDO UI GRID - dynamic columns objects

Hi there im building a grid that have dynamic columns depending on the number of a specific object.. here's a example
public class Team
{
string name {get;set;}
List<members> memberslist {get;set;}
}
public class member{
string name {get;set;}
int goals {get;set;}
}
in the view:
#(Html.Kendo().Grid(Model.TeamList)
.Name("goalslist")
.Columns(columns =>
{
columns.Bound(team => team.name).Title("Team Name");
columns.Bound(team => team.memberslist);
}...
what i would like the result was something like this:
Team Name, John Smith Taylor Fernandez
Ajax       22      1     3
Milan      0      1      2
Any Ideia?! how its done will print object[object], i tried a lot of stufs but without sucess.. thanks
The easiest way to do this is through JSON. Convert your column list into json and pass it to the column, see below. At the very bottom you can see me pushing the columns to the grid. Below that you can see what the JSON itself looks like.
var gridJSON = {
dataSource: {
data: data,
schema: {
model: {} // the model gets filled in by the JSON coming from the database
},
pageSize: 20
},
height: 550,
groupable: false,
sortable: true,
resizable: true,
filterable: {
extra: false,
operators: {
string: {
startswith: "Starts with",
eq: "Is equal to",
neq: "Is not equal to"
}
}
},
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
toolbar: kendo.template($("#template").html())
};
gridJSON.columns = currentReport.JSON.columns;
gridJSON.dataSource.schema.model.fields = currentReport.JSON.fields;
Here is the JSON for the 'currentReport.JSON.columns'
"columns" : [{
"field" : "ReceiverID",
"title" : "Receiver ID"
}, {
"field" : "ReceiverBatchID",
"title" : "Batch ID"
}, {
"field" : "PoNumber",
"title" : "PO Number"
}, {
"field" : "ReceiverTransactionDate",
"title" : "Receiver Trans Date",
"format" : "{0: yyyy-MM-dd}"
}, {
"field" : "PrintingLocation",
"title" : "Location"
}, {
"field" : "VendorID",
"title" : "Vendor ID"
}, {
"field" : "InNemo",
"title" : "InNemo"
}, {
"field" : "Path",
"title" : "Path",
"encoded" : "true",
"template": "#=Path#",
"width" : "50"
}
]

Rails Mongoid geo_near sort by distance

What I'm trying to do is to sort mongoid geo_near(or within_circle) max_distance results by distance because I don't know why but it doesn't do that by default.
I have mongoid_geospatial, mongoid_spacial and rgeo in my Rails gem file. I know mongoid_spacial has this ability but I could not use it and it caused problems with gmaps4rails.
I'm trying on mongoid_geospatial(which uses mongoid libraries) with no success and I could not find any resource except this one https://stackoverflow.com/questions/18633636/mongodb-aggregate-geonear-maxdistance but I don't know how to convert mongo that to mongoid.
Any one had an experience on sorting geo_near or within_circle in mongoid? Any help will be greatly appreciated.
The code in my Controller
searchterm = session[:categoryid].to_s
radius = session[:distance].to_f / 10
#places = Provider.all.where(:category.to_s => /.*#{searchterm}.*/)
.geo_near([ session[:latitude].to_f,session[:longitude].to_f ]).max_distance(radius)
##places = Provider.all.where(:category.to_s => /.*#{searchterm}.*/)
#.within_circle(location: [[ session[:latitude].to_f,session[:longitude].to_f ], radius ])
#.sort(:servicescore.desc).sort(:pricescore.desc)
The code in my model
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::Paranoia
include Mongoid::Geospatial
include Mongoid::MultiParameterAttributes
include Mongoid::Slug
include Mongoid::Spacial::Document
include Gmaps4rails::ActsAsGmappable
acts_as_gmappable :lat => 'latitude', :lon => 'longitude', :process_geocoding => true,
:check_process => :prevent_geocoding,
:address => "business_address"
field :location, :type => Point
spatial_index :location
field :officialname
field :business_description
field :category#, :type => Array
field :business_type
field :tax_office
field :tax_number
field :pin
field :business_phone
field :web_site
field :business_address
field :latitude
field :longitude
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
EDIT ON QUESTION
I've tried almost anything related without success. Read mongo and mongoid geo_near documentation. It does comment on storing location [lon, lat] order. I've tried both [lon, lat] and [lat, long] both when saving the provider and for the center location. Tried spherical geo_near and within_circle too. Still without success.
Geo_near returns my results incorrectly ordered as seen on the map above and on the list below. There should be something I'm missing but can't find it.
The red parts are the "geo_near_distance" output results, the list is sorted according to those but they are wrong as seen on the map. The green calculation is jquery code I've been using that returns correct distances(though cannot use in controller).
There should be something I'm missing. Can anyone spot that?
here is my latest code:
Provider.rb
field :location, :type => Array # [lat,lng]
index({ location: "2d" }, { min: -180, max: 180 })
spatial_index :location
Providers_controller
center = [session[:longitude].to_f, session[:latitude].to_f]
radious = 100
searchterm = session[:categoryid].to_s
radius = session[:distance].to_f / 10
#places = Provider.all.where(:category.to_s => /.*#{searchterm}.*/)
.geo_near(center).max_distance(radious)#.spherical
#.near(location: center)
#.within_circle( location: [center,radius] )
#.sort(:geo_near_distance.desc)
#.geo_near([ session[:latitude].to_f,session[:longitude].to_f ]).max_distance(100).spherical
#.unit("km")
#.geo_near([ session[:latitude].to_f,session[:longitude].to_f ], max_distance: radius, unit: "km".to_sym, spherical: true).sort_by!{|r| r.geo[:distance] }
#.geo_near([ session[:latitude].to_f,session[:longitude].to_f ]).max_distance(radius)
#.sort(:geo_near_distance)
JQuery for the green part
var p1 = new LatLon(Geo.parseDMS($('#lat1_{{id}}').val()), Geo.parseDMS($('#lon1_{{id}}').val()));
var p2 = new LatLon(Geo.parseDMS($('#lat2_{{id}}').val()), Geo.parseDMS($('#lon2_{{id}}').val()));
var new_number = parseFloat(p1.distanceTo(p2)).toFixed(2);
$('#result-distance_{{id}}').html(new_number+' km');
Data for Provider
{ "_id" : ObjectId("5295ef0fdd5063ce1600002a"), "workdonecount" : 0, "pricescore" : 0, "servicescore" : 0, "_slugs" : [ "5295ef0fdd5063ce1600002a-1" ], "officialname" : "çeşme", "business_description" : "dsadsa", "category" : "5280ad334b315241af406c79", "business_type" : "Ticari", "tax_office" : "dads", "tax_number" : "dss", "pin" : "", "business_address" : "Balçova/İzmir, Türkiye", "latitude" : 38.3692939, "longitude" : 27.093442, "pink" : false, "hizmetkutusu_verified" : false, "user_id" : ObjectId("52946f54dd50636df6000002"), "location" : [ 27.093441999999982, 38.3692939 ], "gmaps" : true, "updated_at" : ISODate("2013-11-27T13:09:36.214Z"), "created_at" : ISODate("2013-11-27T13:09:36.214Z") }
{ "_id" : ObjectId("5295f248dd5063ce16000030"), "workdonecount" : 0, "pricescore" : 0, "servicescore" : 0, "_slugs" : [ "5295f248dd5063ce16000030-1" ], "officialname" : "izmirdsads", "business_description" : "dsdsadsdsa", "category" : "5280ad334b315241af406c79", "business_type" : "Ticari", "tax_office" : "dasds", "tax_number" : "dadsa", "pin" : "", "business_address" : "Çeşme, Türkiye", "latitude" : 38.32980999999999, "longitude" : 26.3149209, "pink" : false, "hizmetkutusu_verified" : false, "user_id" : ObjectId("52946f54dd50636df6000002"), "location" : [ 26.31492090000006, 38.32980999999999 ], "gmaps" : true, "updated_at" : ISODate("2013-11-27T13:23:20.423Z"), "created_at" : ISODate("2013-11-27T13:23:20.423Z") }
{ "_id" : ObjectId("5295f260dd5063ce16000032"), "workdonecount" : 0, "pricescore" : 0, "servicescore" : 0, "_slugs" : [ "5295f260dd5063ce16000032-1" ], "officialname" : "dsadsa", "business_description" : "dsadsa", "category" : "5280ad334b315241af406c79", "business_type" : "Ticari", "tax_office" : "dsadsa", "tax_number" : "dsads", "pin" : "", "business_address" : "Çiğli, 35580 İzmir, Türkiye", "latitude" : 38.496303, "longitude" : 27.0603911, "pink" : false, "hizmetkutusu_verified" : false, "user_id" : ObjectId("52946f54dd50636df6000002"), "location" : [ 27.06039110000006, 38.496303 ], "gmaps" : true, "provider_image" : "gmaps1.jpg", "updated_at" : ISODate("2013-11-27T13:23:44.686Z"), "created_at" : ISODate("2013-11-27T13:23:44.686Z") }
{ "_id" : ObjectId("5295eee3dd5063ce16000026"), "workdonecount" : 0, "pricescore" : 0, "servicescore" : 0, "_slugs" : [ "5295eee3dd5063ce16000026-1" ], "officialname" : "dsdsa", "business_description" : "dadsa", "category" : "5280ad334b315241af406c79", "business_type" : "Ticari", "tax_office" : "dsa", "tax_number" : "dads", "pin" : "", "business_address" : "Buca, İzmir, Türkiye", "latitude" : 38.38813400000001, "longitude" : 27.1753358, "pink" : false, "hizmetkutusu_verified" : false, "user_id" : ObjectId("52946f54dd50636df6000002"), "location" : [ 27.291124800000034, 38.3337361 ], "gmaps" : true, "updated_at" : ISODate("2013-11-27T13:08:51.544Z"), "created_at" : ISODate("2013-11-27T13:08:51.544Z") }
{ "_id" : ObjectId("5295eef5dd5063ce16000028"), "workdonecount" : 0, "pricescore" : 0, "servicescore" : 0, "_slugs" : [ "5295eef5dd5063ce16000028-1" ], "officialname" : "dsdsdsa", "business_description" : "dadsds", "category" : "5280ad334b315241af406c79", "business_type" : "Ticari", "tax_office" : "dasds", "tax_number" : "dadsa", "pin" : "", "business_address" : "Bornova, 35100 İzmir, Türkiye", "latitude" : 38.466414, "longitude" : 27.2192191, "pink" : false, "hizmetkutusu_verified" : false, "user_id" : ObjectId("52946f54dd50636df6000002"), "location" : [ 27.219219100000032, 38.466414 ], "gmaps" : true, "updated_at" : ISODate("2013-11-27T13:09:10.122Z"), "created_at" : ISODate("2013-11-27T13:09:10.122Z") }
I used it few months ago. This is how I used it:
class Person
include Mongoid::Document
field :location, :type => Array # [lat,lng]
index( { location: Mongo::GEO2D }, { min: -180, max: 180 })
end
Then you need to generate indexes:
rake db:mongoid:create_indexes
Then you can make the query:
center = [ 1, 10 ]
radious = 100
Person.within_circle( location: [ center, radious ] )
Or use $near query:
Person.geo_near(center).max_distance(radious) # sorted by distance
All information is specified here:
http://mongoid.org/en/mongoid/docs/indexing.html
http://mongoid.org/en/origin/docs/selection.html
http://mongoid.org/en/mongoid/docs/querying.html#geo_near
Good luck!

Resources