MongoDB Query if (Field A - Field B) > N - ruby

I have been stuck on this for several hours now. I need to write a query that returns all documents where (Field A - Field B) > N
// sample data
{ _id: '...', estimated_hours: 0, actual_hours: 0 },
{ _id: '...', estimated_hours: 10, actual_hours: 9 },
{ _id: '...', estimated_hours: 20, actual_hours: 30 }
Borrowing answers from this stack question I wrote the below, In my mind this should have worked, however I am consistently getting records back that do not match the query...
## Attempt 1
n = 0
records = API::Record.where('$where': "(this.estimated_hours - this.actual_hours) > #{n}")
## should return the following, but im getting additional records
#=> [{ _id: '...', estimated_hours: 10, actual_hours: 9 }]
I know I can likely accomplish this with $project however i have to explicitly tell $project what fields I want returned. I need all the fields to be returned, we use a third party library that handles pagination

play
db.collection.find({
$where: "(this.estimated_hours - this.actual_hours) > 1"
})
Similar example for reference

Related

amount of character which are between epiosde 1 and 2 with the name Rick

I have a problem. I am using the https://rickandmortyapi.com/graphql API for graphql. I want to query the amount of character which are between epiosde 1 and 2 with the name Rick. Unfortunately my query is wrong. How could I get the desired output. I want to use the _" ..."Meta to get the meta data.
query {
characters(filter: {name: "Rick"}) {
_episode(filter: {id : 1
id: 2}) {
count
}
}
}

Enum for number in GraphQL (js)

I want to allow one of the fields to be either 1, 2 or 3. I am not exactly sure how to do that in http://graphql.org/graphql-js/type/
Because I would need to do something like:
var AgeType = new GraphQLEnumType({
name: 'Age',
values: {
1: { value: 0 },
2: { value: 1 },
3: { value: 2 }
}
});
And this doesn't work because the key is a number...
It's not possible as described here: https://github.com/graphql/graphiql/issues/586
GraphQL require enum values to match [_A-Za-z][_0-9A-Za-z] RegExp
Enum variables have to start with a letter, so you will have to use String or Int type. In order to ensure that only 1,2 and 3 are passed, you may implement some kind of validation rules in the resolvers.

Faster query by value

I want to query MongoDB to find, in the results top level document, how many nested documents of it have value 0.
For instance, in this collection:
{name: "mary", results: {"foo" : 0, "bar" : 8}}
{name: "bob", results: {"baz" : 9, "qux" : 0}}
{name: "leia", results: {"foo" : 9, "norf" : 5}}
my query should return 2, because two of the documents have 0 as a value of a nested document of results.
Here's my attempt
db.collection.find({$where : function() {
for (var key in this.results) {
if (this.results[key] === 0) { return true;} } return false; } })
which works on the above dataset, but is too slow. My real data are 100k documents, each having 500 nested documents inside results, and the above query takes a few minutes. Is it possible to design this query in a faster way?
There is no way to do it, other than the one you are doing.
You can only change the schema or use aggregations but I don't think that this is what you want.
There is a post about it you can check here:
mongoDB: find by embedded value

Ruby Mongodb driver $gt acts as $gte in date conditions, why?

I have a weird situation with $gt and $gte conditions in ruby mongodb driver.
So here is code:
timeline = timeline_db.find({date: {"$gt" => s_time}, username: { "$in" => followers_array } }, sort:["date", Mongo::DESCENDING], limit: 10)
Problem is that this query return item with exactly that time I'm requesting, which would be valid if I wrote $gte instead.
$gte does return exactly same result as $gt. Why does it happen?

increment value in a hash

I have a bunch of posts which have category tags in them.
I am trying to find out how many times each category has been used.
I'm using rails with mongodb, BUT I don't think I need to be getting the occurrence of categories from the db, so the mongo part shouldn't matter.
This is what I have so far
#recent_posts = current_user.recent_posts #returns the 10 most recent posts
#categories_hash = {'tech' => 0, 'world' => 0, 'entertainment' => 0, 'sports' => 0}
#recent_posts do |cat|
cat.categories.each do |addCat|
#categories_hash.increment(addCat) #obviously this is where I'm having problems
end
end
end
the structure of the post is
{"_id" : ObjectId("idnumber"), "created_at" : "Tue Aug 03...", "categories" :["world", "sports"], "message" : "the text of the post", "poster_id" : ObjectId("idOfUserPoster"), "voters" : []}
I'm open to suggestions on how else to get the count of categories, but I will want to get the count of voters eventually, so it seems to me the best way is to increment the categories_hash, and then add the voters.length, but one thing at a time, i'm just trying to figure out how to increment values in the hash.
If you aren't familiar with map/reduce and you don't care about scaling up, this is not as elegant as map/reduce, but should be sufficient for small sites:
#categories_hash = Hash.new(0)
current_user.recent_posts.each do |post|
post.categories.each do |category|
#categories_hash[category] += 1
end
end
If you're using mongodb, an elegant way to aggregate tag usage would be, to use a map/reduce operation. Mongodb supports map/reduce operations using JavaScript code. Map/reduce runs on the db server(s), i.e. your application does not have to retrieve and analyze every document (which wouldn't scale well for large collections).
As an example, here are the map and reduce functions I use in my blog on the articles collection to aggregate the usage of tags (which is used to build the tag cloud in the sidebar). Documents in the articles collection have a key named 'tags' which holds an array of strings (the tags)
The map function simply emits 1 on every used tag to count it:
function () {
if (this.tags) {
this.tags.forEach(function (tag) {
emit(tag, 1);
});
}
}
The reduce function sums up the counts:
function (key, values) {
var total = 0;
values.forEach(function (v) {
total += v;
});
return total;
}
As a result, the database returns a hash that has a key for every tag and its usage count as a value. E.g.:
{ 'rails' => 5, 'ruby' => 12, 'linux' => 3 }

Resources