How to access dynamic attribute 'geo_near_distance' with Mongoid - ruby-on-rails

I am using Mongoid 3.1.6 with Rails 4. I need to find all the objects 'near' a certain co-ordinate. For each result from the search, I will need to display the distance from the search co-orodinate. According to Mongoid Documentation
...each instantiated document from a $geoNear query will get a special
dynamic attribute geo_near_distance that will be available as long as
the document is in memory.
But I am not able to access the Object.geo_near_distance
My query inside controller...
#objects = Object.geo_near([-118.4451, 34.0633]).max_distance(10)
Edit#1
Some additional details
If the use the following query in MongoDB
db.runCommand( { geoNear: "objects",
near: [ -73.95269,40.77578],
spherical: true
})
I see an array of 100 elements. Each element has 2 attributes. The first one, 'dis' has values like '0.000123' (Note: this is not in Km or Mile) and the second attribute is the result Object itself.
Now I have changed the query to Mongoid to...
#objects = Object.geo_near([-118.4451, 34.0633]).spherical.max_distance(10)
still no result.
Thanks in advance for your help.

After more than 2 years, the issue ticket is still open on mongodb jira tracker.
The quick fix is not use the hash notation instead of the dot notation to access the attribute:
Instead of
Object.geo_near_distance
Use
Object['geo_near_distance']
Tested on mongoid 6

Are you accessing the field while you are iterating the documents? You can see by the specs that this field is in fact there when the document is in memory and is being part of the iteration of the criteria result.
https://github.com/mongoid/mongoid/blob/master/spec/mongoid/contextual/geo_near_spec.rb#L167

Related

Multiple nesting in Falcor query

I am trying to query a multiple nested object with Falcor. I have an user which has beside other the value follower which itself has properties like name.
I want to query the name of the user and the first 10 follower.
My Falcor server side can be seen on GitHub there is my router and resolver.
I query the user with user["KordonDev"]["name", "stars"]. And the follower with user["KordonDev"].follower[0.10]["name", "stars"].
The route for follower is user[{keys:logins}].follower[{integers:indexes}] but this doesn't catch the following query.
I tried to add it as string query.
user["KordonDev"]["name", "stars", "follower[0..10].name"] doesn't work.
The second try was to query with arrays of keys. ["user", "KordonDev", "follower", {"from":0, "to":10}, "name"] but here I don't know how to query the name of the user.
As far as I know and looking on the path parser. There is no way to do nested queries.
What you want to do is batch the query and do two queries.
user["KordonDev"]["name", "stars"]
user["KordonDev"]["follower"][0..10].name
It seems that falcor does not support this, there is even a somewhat old issue discussing how people trying to do nested queries.
to the point about the current syntax leading people to try this:
['lolomo', 0, 0, ['summary', ['item', 'summary']]]
I can see folks trying to do the same thing with the new syntax:
"lolomo[0][0]['summary', 'item.summary']"
As soon as they know they can do:
"lolomo[0][0]['summary', 'evidence']"
So it seems deep nested queries is not a functionality.

Rails manipulate model query

Assume I have params[:foo] = "bar" and some saved object whose attribute = "key.bar"
How can I manipulate Model.where(attribute: params[:foo]) to query for attribute.split(".")[1] ?
I'm not certain if there's a better way, but the first method that popped in my mind is using the LIKE operator. You can write your query thusly:
Model.where("attribute LIKE '%?'", params[:foo])
Note, given the example you posted, I placed the wildcard (%) in that position so that the attribute is match for anything that ends with your parameter. This assumes all your attributes are similar to what you described, but you can of course change it around to your liking.
Also, while I've never used it myself, I understand that the Squeel gem provides this functionality as an operator (described here).
Small change to answer above
Model.where("attribute LIKE '%.?'", params[:foo])
to prevent matching both .bar and .foobar.

AcitveRecord where method that matches just one record

Program.where(name: "xxyyzz123") will return a collection, even if there's just one record that matches which forces me to do ugly things like:
puts Program.where(name: "xxyyzz123").first.age
or
puts Program.where(name: "xxyyzz123")[0].age
When I know for sure only one record will match, is there a shorter way to grab a property from that one record?
ActiveRecord's dynamic attribute-based finders (find_by_x) allow you to select the first record that matches in your database. For example:
Program.find_by_name('xxyyzz123')
will return the first record with name = 'xxyyzz123'
Note that these finders are 'mildly deprecated' in Rails 4. Using
Program.find_by(name: 'xxyyzz123")
achieves the same thing and may make it easier when needing to update to the next version of Rails if they ever remove the former's functionality.
See ActiveRecord::Base in the API for more.
Yes, you will have to access that with Program.where(name: "xxyyzz123").first.age, however, in Rails 3, it is usually recommended to do that type of query with: Program.find_by_name('xxyyzz123').age.
Rails 4 deprecates the above syntax and recommends you to use the following syntax for that:
Program.find_by(name: 'xxyyzz123')
If you have multiple conditions, then simply : Program.find_by(name: 'xxyyzz123', lang: 'ruby')
Behind the scene, it does the same tomfoolery - where clause and returns first object.

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

Getting Mongoid from params array

In order to find a Root Document that contains a embedded document using MongoID/Rails 3 I need to do my query this way:
QuoteRequest.where( "order_request_items._id" => BSON::ObjectID(params[:id]) ).first
Is there a way to query without using the BSON::ObjectID ?
Thanks!
I'm not a MongoID/Rails user, but my guess is that you can't.
Even in the Mongo shell you have to use ObjectId() if you want to compare ObjectIDs. Something like this won't return any results:
db.foo.find({_id: "4c7ca651db48000000002277"})
You'll have to create an actual ObjectID from the string in order to get results:
db.foo.find({_id: ObjectId("4c7ca651db48000000002277")})
MongoID apparently doesn't automatically convert your input to ObjectIDs. But perhaps there's a way to tell MongoID which fields it should always convert to ObjectIDs? Then you would be able to omit the use of BSON::ObjectID.
This is a bug, the ids should be automagically converted by Mongoid. You should open a ticket on github: http://github.com/mongoid/mongoid/issues

Resources