Compare separate columns in Mongoid - ruby-on-rails

I'm looking for the mongoid equivalent to:
How to select the comparison of two columns as one column in Oracle
I can't seem to find any documentation or examples comparing columns within the same query. Is this just not possible in Mongoid?

Nope, you need to drop down to the mongodb ruby driver to do this and it will potentially be very slow as it is a javascript query that will not use an index:
Model.collection.find_one({"$where" => 'this.name == this.name2'})
Which is equivalent to third shell command here.:
> db.collection.insert({name: "awesome", name2: "awesome"})
> db.collection.insert({name: "awesome", name2: "awesome2"})
> db.collection.find('this.name == this.name2')
{ "_id" : ObjectId("xxx"), "name" : "awesome", "name2" : "awesome" }
> (line shown to signify end of results)
Note: if a document does not have key name and that same document also does not have key name2 that this will return true because null == null.

Related

Elasticsearch match field=value (not contains)

I have problem while searching through elasticsearch.
I have index product with fields title and gender
When I make query with default_field: title I need to get results only with gender=male (not female or others)
query: dress AND gender:male
Results contain both genders: male and female and male,female
It seems to me that gender:* search all which contains male, but not full match of value. How to do the query right?
I use it through Ruby on Rails
Product.search({
query: {
query_string: {
query: query,
default_field: "title"
}
},
size: per_page,
sort: [ _score: { order: relevance } ]
})
Is gender a keyword data type? I suspect that you left/set the default mapping to the gender field (i.e., text + keyword subfield). In this case, try the following query: dress AND gender.keyword:male
According with this I just need to put value in double quotes..
query = '(dress) AND (gender:"male")'
do not forget to escape them if needed "gender:\"male\""

Hstore Query to find records matching with any array element using ruby on rails

I've a hstore field in a database table. I want to write a Query to find records matching with any array element in any hash of hstore field using ruby on rails.
Users Table
--------------------------------------------------------------------------------
ID Name sectors(hstore)
1 Piotr {"aviation"=>"0", "oil_and_gas" => "50", "transport" => "50"}
2 reza {"oil_and_gas" => "70", "energy" => "30"}
3 pat {"transport" => "40", "energy" => "60"}
4 Kim {"infrastructure" => "20", "healthcare" => "20", "industrial" => "60"}
considering above test data, I want to write a query on hstore field to get all records having any key like ['oil_and_gas', 'energy', 'transport']
I can match and find single sector records as its mentioned in https://nandovieira.com/using-postgresql-and-hstore-with-rails, but my requirement is to find any record where hstore hash is having any one key matching with any one element of array.
I'm using Rails 5.1.6.2, ruby 2.5.3
May be you are looking for the following operator:
hstore ? key # does hstore contain key?
Query may looks like so:
User.where("sectors ? 'oil_and_gas'")
.or("sectors ? 'energy'")
.or("sectors ? 'transport'")
According to postgresql docs
Check for a specific key in hstore column You can check for a specific
key in an hstore column using the ? operator in the WHERE clause. For
example, the following statement returns all rows with attr contains
key publisher.
SELECT
title,
attr->'publisher' as publisher,
attr
FROM
books
WHERE
attr ? 'publisher';

Querying jsonb array for partial value

In a Rails 5.2 app, the User model has the subscriptions jsonb attribute
t.jsonb "subscriptions", default: [], null: false
An example is
irb(main):091:0> User.first.subscriptions
=> [{"id"=>"dfdaad60", "type"=>"Organization"},
{"id"=>"18616f4d", "type"=>"Project"}]
How can I, using arel, get the ids of all the subscriptions having type equal Project?
I have tried to use the #> operator without success.
Following will return array of ids for subscriptions(having type 'Project') of Users,
User.pluck(:subscriptions).flatten.map { |x| x['id'] if x['type'] == 'Project' }.compact
You do not need where AR or AREL query as you need only ids present inside subscriptions for type having 'Project' & can be get as above.
This will do the trick, using a custom SQL statement:
sql = "SELECT value->'id' AS id FROM users, jsonb_array_elements(users.subscriptions) WHERE data #> '#{[{type: "Project"}].to_json}'"
result = ActiveRecord::Base.connection.execute(sql)
puts result.to_a
You can use the ActiveRecordExtended gem to find all users which have a project type subscription:
User.where.contains(subscriptions: { type: "Project" })
I would then get ids in ruby.

Is it possible to upsert documents in mondodb by an array of ids, so that each new created document's _id is the one from the array?

In my Rails project with mongodb, I retrieve user ids from twitter which I want to store in my User model. The plan is to upsert the collection of Users with the retrieved user ids I have in an array, and set every new created document _id to the corresponding user id from the array.
So when I do something like this:
Tweep.collection.find( _id: 1234567 ).modify( { "$set" => {a: true}, "$unset" => {c: ""} }, {upsert: true})enter code here
The result is like expected: <Tweep _id: 1234567, a(active): true, c(candidate_value): nil>
Now I want to do the same, but only passing an array of ids to upsert my collection on Users:
Tweep.collection.find(_id: {"$in" =>[123124,223553,6343643,23423]}, c: { "$exists" => true }).modify( { "$set" => {p: true}, "$inc" => {c: 1} }, {upsert: true})
The result is some newly created documents, but without the desired values as _id e.g. _id: 123124:
<Tweep _id: 5244501325fed0cfd2c1a615, a(active): nil, c(candidate_value): 1>
instead of:
<Tweep _id: 123124, a(active): nil, c(candidate_value): 1>
How can I make mongodb use the user id in my array to be the id for the field _id?
Any help is highly appreciated.
That is not possible. From the documentation:
If upsert is set to true and if no document matches the query
criteria, update() inserts a single document.
Then again, you write:
The result is some newly created documents
I hope that it's really only one document. With a query that contains only _id : {$in : [...]}, it wouldn't even insert a single document on my machine (MongoDB 2.5.0). It only inserts if I add more criteria. Could you check that again?
It's hard to come up with a meaningful definition of how this should behave. Combining $in can be tricky. Let's say you have two documents:
{ _id : 1, name : "John" }
{ _id : 2, name : "Jane" }
and you call
db.update({"_id" : {$in : [1,2]}, "name" : "Max"}, { ... }, { upsert: true});
What is supposed to happen? There is no document that has _id 1 or 2 and name equals "Max", so the upsert would have to insert... well, what? Maybe two documents with the name Max? If the array were larger, we'd create a ton of 'Max's which probably wasn't our intention (the semantics would be: "update one or insert a thousand", which is odd). So let's say we only insert one. But now, which _id to choose? And, of course, there is the problem that _id is a unique key, so in the example, both would fail.

Ruby sort_by with null values

Using Ruby on Rails. I'm trying to sort a query by number (saved as string) and letter. However, my letter column can contain "NULL" values. This crashes when there are Null values in the letter column:
#fences = Fence.find(:all,
:conditions => ["coursewalk_id = #{#coursewalk.id}"]).sort_by { |a| [+(a.number.to_i), a.letter] }
How can I fix this?
a.letter.to_s should do the trick.

Resources