How to find all documents that don't have an array or it is smaller than - ruby

I'm trying to find all documents, which either don't have an array tags or the size of the array is smaller than 2. How do I do this? I'm trying this, but doesn't work:
db.collection.find({
'text' => { '$exists' => true }, # I need this one too
'tags' => {
'$or' => [
{ '$exists' => false },
{ '$lt' => ['$size', 2] }
]
}
})
It's Ruby, btw. MongoDB version is 4.
I'm getting:
unknown operator: $or

You can use below query
db.collection.find({
text: { $exists: true },
$or: [{
tags: { $exists: false }
}, {
$expr: { $lt: [{ $size: '$tags' }, 2] }
}]
})

To slightly modify MauriRamone's answer to a smaller version:
db.getCollection('test').find({
$and:[
{"text":{$exists:true} },
{$where: "!this.tags || this.tags.length < 2"}
]
})
However, $where is slow, and other options (such as Anthony's) should be preferred.
Your original query wasn't working because $or only works in expressions, not in fields, and you need an $expr operator for the size.

try using $were in your query, like this:
db.getCollection('test').find({
$and:[
{"text":{$exists:true} },
{
$or:[
{"tags":{$exists:false}},
{$where: "this.tags.length < 2"}
]
}
]
})
I am using Robomongo to test, you should format the query to Ruby.
regards.

Related

ElasticSearch query for items not in given array

I am trying to write a part of a query to filter out any items with a type as "group" and that have a group id that isn't in a given array of ids. I started writing a bool query with a must and must_not but I was getting tripped up on how to write "id not in the given array.
EDIT:
I am actually converting an outdated query using "and" and "not" to be ES 5.5 compatible. Here is the old query that worked.
:and => [
{
term: {
type: 'group'
}
},
{
:not => {
terms: {
group_id: group_ids
}
}
},
{
:not => {
terms: {
user_id: user_ids
}
}
}
]
group_ids and user_ids are arrays.
You probably have not analyzed the arrays with the IDs. You can use a Bool query with a filter clause, and then within that filter start a new bool query with a mustNot clause and within that clause add a terms query with your IDs.
bool: {
must: {
term: {
kind: 'group'
}
},
must_not: [
{
terms: {
group_id: group_ids
}
},
{
terms: {
user_id: user_ids
}
}
]
}

How to use ReQL filter and match command on arrays

I have a table in rethinkdb where each row has following structure -
{
'name':'clustername',
'services':[
{
'name':'service1'
},
{
'name':'service2'
}
]
}
I am running a query to filter service2 object like this
r.table('clusters').filter({"name": "clustername"})
.pluck('services').filter((service) => {
return service("name").match('service2')
})
But this is not returning anything: No results were returned for this query
Can anyone tell why this is happening?
pluck returns sequence, so this query:
r.table('clusters').filter({"name": "clustername"}).pluck('services')
will return:
{
"services": [
{
"name": "service1"
} ,
{
"name": "service2"
}
]
}
You need get services field from it, it will return array with services field of items found by filter.
And after that you need to use your second filter on each item by using map.
So, correct query:
r.table('clusters').filter({"name": "clustername"}).pluck('services')("services").map(item => {
return item.filter(service => {
return service("name").match("service2");
});
})

How can i get avg,sum of sub attribute?

I have problem with writing average query!
In my Rethink db, i have some documents in one table like this:
document1:
{
a:{
last:3
},
b:{
last:4
},
c:{
last:6
},
}
document2:
{
a:{
last:7
},
b:{
last:9
},
c:{
last:2
},
}
document3:
{
a:{
last:5
},
b:{
last:8
},
c:{
last:4
},
}
I want to get average of last attribute in every object like this:
{
sum_a_last:15,
sum_b_last:21,
sum_c_last:12,
avg_a_last:5,
avg_b_last:7,
avg_c_last:4
}
What is the query to return this result?
I believe what you're looking for is
r.db('dbName').table('tableName').avg((doc) => doc('a')('last'));
If you're trying to dynamically look for the last member for all objects in a doc there will obviously be more work.
https://rethinkdb.com/api/javascript/avg/

"OR" query in KeystoneJS Relationship Filters

Currently, all I see examples for is:
{
team: ':team'
}
But I need to be able to filter by multiple values ($or query)
Something like:
winner: {
type: Types.Relationship,
ref: 'Team',
filters: [
{
_id: ':homeTeam'
},
{
_id: ':awayTeam'
}
]
}
Is this possible?
Try the following code:
filters:{_id:{$in:[id_array]}}

Mongo full text search with score via Ruby driver

In the Mongo documentation, it says you can do this:
db.articles.find(
{ $text: { $search: "cake" } },
{ score: { $meta: "textScore" } }
)
That works fine when I run it from the mongo console but I can't figure out how to do that via the Ruby driver.
When I do this:
articles.find('$text': { '$search': 'cake' }, score: { '$meta': 'textScore' })
I get
Mongo::Error::OperationFailure: unknown operator: $meta (2)
When I do
articles.find({ '$text': { '$search': 'cake' } }, score: { '$meta': 'textScore' })
I get results but it doesn't include the score and the log message doesn't show that it's using the score: { $meta': 'textScore' }:
{"find"=>"articles", "filter"=>{"$text"=>{"$search"=>"cake"}}}
I guess I just don't grok how the Ruby driver and Mongo CLI convert those into Mongo queries.
I'm using MongoDB version v3.2.7 and the mongo gem version 2.2.5.
Let's look to structure of mongo command:
db.collection.find(
<query>,
{ score: { $meta: "textScore" } }
)
We see that command contains two parts (in this case find)
<query>
options hash
Structure of command in mongo-driver very similar to mongo. But some things are not simple.
In mongo-driver we have Mongo::Collection::View, check (link to source):
articles.find({ '$text': { '$search': 'cake' } }.class # => Mongo::Collection::View
So after analyzing code, i found that you can use projection option, but it is tricky:
articles.find(
{ "$text" => { "$search" => "cake" } },
projection: {
"score" => { "$meta" => "textScore" },
some_field: 1
})
My test was:
posts.find(
{ "$text" => { "$search" => "house" } },
projection: { "score" => { "$meta" => "textScore" }, rooms: 1 }
)
Results is:
{"_id"=>BSON::ObjectId('53f5c8b54465764a82fb0000'),
"rooms"=>2.0,
"score"=>0.5004448398576512}
#farhatmihalko's answer is spot-on. To add to it, this also works:
posts
.find("$text": { "$search": "house" })
.projection(score: { "$meta": "textScore" }, rooms: 1)

Resources