Mongo Spring Projection Query - spring

Hi I am trying to get the below mongo query into spring mongo. I've been trying different ways but I am very fusturated right now. Need help!
db.getCollection('rate_review').aggregate([
{$match:{stars:{$exists:true}}},
{$group:{_id:"$store_id",count:{$sum:"$stars"}, maxCount:{$sum:1}}},
{ $project: { _id: 1, rating:
{
$divide: [ "$count",
{
$multiply: [ "$maxCount", 5 ]
}
]
},
"timestamp":{$add:new Date()} } }
])
This is what I have so far,
return mongoTemplate.aggregate(newAggregation(
match(Criteria.where("stars").exists(true)),
group("$storeId").sum("$stars").as("count").sum("$stars").as("maxCount")
).withOptions(newAggregationOptions().allowDiskUse(true).build()), StoreReview.class, Object.class).getMappedResults();
I need help with the Projection piece.

Related

Graphql: How can I solve the N + N problem?

After having implemented dataloader in the respective resolvers to solve the N+1 problem, I also need to be able to solve the N+N problem.
I need a decently efficient data loading mechanism to get a relation like this:
{
persons (active: true) {
id,
given_name,
projects (active: true) {
id,
title,
}
}
}
I've created a naive implementation for this, returning
{
persons: [
{
id: 1,
given_name: 'Mike'
projects: [
{
id: 1,
title: 'API'
},
{
id: 2,
title: 'Frontend'
}
]
}
{
id: 2,
given_name: 'Eddie'
projects: [
{
id: 2,
title: 'Frontend'
},
{
id: 3,
title: 'Testing'
}
]
}
]
}
In SQL the underlying structure would be represented by a many many to many relationship.
Is there a similiar tool like dataloader for solving this or can this maybe even be solved with dataloader itself?
The expectation with GraphQL is that the trip to the database is generally the fastest thing you can do, so you just add a resolver to Person.projects that makes a call to the database. You can still use dataLoaders for that.
const resolvers = {
Query: {
persons(parent, args, context) {
// 1st call to database
return someUsersService.list()
},
},
Person: {
projects(parent, args, context) {
// this should be a dataLoader behind the scenes.
// Makes second call to database
return projectsService.loadByUserId(parent.id)
}
}
}
Just remember that now your dataLoader is expecting to return an Array of objects in each slot instead of a single object.

does anyone know how to transform this query from mongo to mongo template?

what i want to do is first transform this query to mongo template
db.project.aggregate([
{
$project: {
boos:1,
"errors":{
$cond: {
if: { $eq : [ 3,"$error.status" ] },
then: '$$REMOVE',
else: "$error"
}
}
}
}
])
the goal is to bring all the projects and errors, however to show the errors as null or blank if their status is 3
If you just want to find all the projects whose status is 3:
Query query = new Query();
query.addCriteria(Criteria.where("status").is(3));
List<Project> projects = mongoTemplate.find(query, "project");

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");
});
})

"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