Here is a simple scenario
I want to query GraphQL and fetch all the students that have attended school more then 200 days this year.
I have a Student sequelize model, a matching GraphQL Object, a students Query which accepts the days int as an argument { students(days:200) }
What I'm obviously trying to do is to implement the logic "get all students where school_visits counter is greater than 200" just as an example...
I'm using graphql-sequelize to glue between sequelize and GraphQL.
a simple example query definition looks like this:
students: {
type: new GraphQLList(Student),
args:{
id : {type:GraphQLInt},
days: {type:GraphQLInt}
},
resolve: resolver(models.Student)
}
as you can notice, this structure doesn't allow me to insert some logic to the query...
If you had any experience working with GraphQl and Sequelize - this is a very generic situation... I'd appreciate any help resolving it.
Cheers
Ajar
Looking at the Sequelize docs, you can try doing something like this in the students resolve function:
resolve(root, args) {
// Assuming you've imported your model
return Db.models.student.findAll({
where: {
days: {
// greater than
$gt: args.days
}
}
});
}
Related
the problem I am facing is as follows:
Search value: 'cooking'
JSON object::
data: {
skills: {
items: [ { name: 'cooking' }, ... ]
}
}
Expected result: Should find all the "skill items" that contain 'cooking' inside their name, using TypeORM and Nest.js.
The current code does not support search on the backend, and I should implement this. I want to use TypeORM features, rather than handling it with JavaScript.
Current code: (returns data based on the userId)
const allItems = this.dataRepository.find({ where: [{ user: { id: userId } }] })
I investigated the PostgreSQL documentation regarding the PostgreSQL functions and even though I understand how to create a raw SQL query, I am struggling to convert this to the TypeORM equivalent.
Note: I researched many StackOverflow issues before creating this question, but do inform me If I missed the right one. I will be glad to investigate.
Can you help me figure out the way to query this with TypeORM?
UPDATE
Let's consider the simple raw query:
SELECT *
FROM table1 t
WHERE t.data->'skills' #> '{"items":[{ "name": "cooking"}]}';
This query will provide the result for any item within the items array that will match exact name - in this case, "cooking".
That's totally fine, and it can be executed as a raw request but it is certainly not easy to maintain in the future, nor to use pattern matching and wildcards (I couldn't find a solution to do that, If you know how to do it please share!). But, this solution is good enough when you have to work on the exact matches. I'll keep this question updated with the new findings.
use Like in Where clause:
servicePoint = await this.servicePointAddressRepository.find({
where: [{ ...isActive, name: Like("%"+key+"%"), serviceExecutive:{id: userId} },
{ ...isActive, servicePointId: Like("%"+key+"%")},
{ ...isActive, branchCode: Like("%"+key+"%")},
],
skip: (page - 1) * limit,
take: limit,
order: { updatedAt: "DESC" },
relations:["serviceExecutive","address"]
});
This may help you! I'm matching with key here.
I'm new to Node.js and Mongoose library. My problem is i have two collections schema
Restaurant
Reviews
I tried to add a virtual field (reviews_count) in Restaurent collection for reviews count.
How can I achieve this one? Is there any specific function available in mongoose?
Restaurant: Reviews:
_id: ObjectId restaurent_id: (Restaurant ref id)
name: String review: String
I expect the output while try to get the restaurant details.
{
"_id": "2344....",
"name": "Restaurant name".
"reviews_count": 220
}
yes, this is possible. There are many ways to do it: You could actually define an async virtual, that will query Reviews, but I don't like this approach too much, since you have to make sure to await it or to handle a callback, which looks and smells bad:
const count = await restaurant.reviews
Alternatively, you could just define an instance method something like this (async would be better, tough), which I like better, since it makes the code easier to read, when calling this function:
// assign a function to the "methods" object of your restaurant schema
restaurant.methods.getReviews = function(cb) {
return this.model('Reviews').find({ restaurant_id: this._id }, cb);
};
Finally, there is a third, and in my opinion the best option: Virtual Populate
Mongoose 4.5 introduced this feature and it perfectly fits your usecase. Define your field like this:
Restaurant.virtual('reviews', {
ref: 'Reviews',
localField: '_id',
foreignField: 'restaurant_id'
});
and then query it like this:
Restaurant.findOne().populate('reviews').exec(function(error, reviews) {
// `reviews.count` is the virtual you are looking for
});
This is imho the cleanest and most versatile solution since it keeps you from unnecessarily adding arrays with refs to you your main object and still get an easy access to all reviews of a restaurant. You can find a good article here:
http://thecodebarbarian.com/mongoose-virtual-populate
Note: This solution might give you performance problems, since we always query the whole review document and not just the count. If you feel like this might be a problem, you might want to first add the .lean() function to your query, and if that doesn't help much, you can resort to one of the first two approaches I outlined.
I will attempt to address the problem as clearly as possible.
Let's say I have two collections, Col_A and Col_B.
Col_A has an attribute, attribute C, that references our other collection, Col_B, via ObjectID.
image for visual reference
I want to query for documents from Col_A and sort by attribute E in Col_B.
A practical example, if the above is too broad, would be Users and Listings on a site like eBay. For this example, let's say Col_A is "Listings", Col_B is "Users", attribute C is "seller", and attribute E is "rating".
Query: grab all listings matching some criteria, sorted by sellers with the highest rating
That would mean "grab all documents from Listings matching some given criteria, and sort the results by the rating attribute for each Users document the listings reference.
How would one go about doing this? I understand how to apply basic sorting logic via mongoose, such as:
Listings.find({"attribute A" : "something"}).sort({"some_field": "uhh"}).exec(function(err, docs) { ... });
, but can I nest in the attributes for referenced documents and sort by those? Do I need to somehow apply queries within the sort parameters or something? Is Mongoose capable of something like this? I looked at Mongoose's populate functionality, but I can't get anything working, and apparently there's a bug that discourages folks from actually using populated documents for sorting.
Github Issue
I apologize if this question has been answered already. I've been digging through the documentation, SO, and various other sites, but I can't get anything going. Thanks in advance!
You could use populate method to populate seller and the query would return an array like this:
[
{
title: 'Listing #1',
seller: {
name: 'John',
rating: 100
}
}
{
title: 'Listing #2',
seller: {
name: 'John',
rating: 20
}
}
]
then you can sort the data like this:
Listings.find({"attribute A" : "something"}).populate('seller').exec(function(err, docs) {
docs.sort(function compare(a, b){
let c = 0;
if (a.seller.rating > b.seller.rating) {
c = 1;
} else if (b.seller.rating > a.seller.rating) {
c = -1;
}
return c;
});
// return or response with docs
});
It might not be what you are looking but I tried :)
Mongo or Mongoose will not do this kind of sort since populate method makes 2 queries and Mongo doesn't know there's any relation between them.
I am trying to figure out the most efficient way to find and populate documents some of which have references to another collection and some don't.
Example:
var collectionA={
{
"topic":"TopicA",
"text";"TextA")
},
{
"topic":"Topic1",
"text":"Text1"}
}
}
var collectionB={
{
"topic":"TopicB",
"text":"TextB"
"reference":["id","id"]
},
{
"topic":"Topic2",
"text":"Text2"
"reference":[]
}
}
and I have a request as follows which allows me to identify the documents I want:
req.body={"topic":["TopicA","TopicB"]}
What is the most efficient way to find the relevant documents and populate them to provide a fully populated result, in the fewest number of database calls as possible:
{"topic":"TopicA","text":"TextA"},
{"topic":"TopicB","text":"TextB","reference":[{populated document}
{populated document}]},
I am trying to use something like:
collections.find({"topic": $in req.body.top}, function(err,result){
collections.populate(result,{path:'references'}, function (err,result){
//do something
});
})
Is this on the right track?
Your help is greatly appreciated.
In order to reference other documents in mongoose you need to use Population.
If you want to reference a topic by id you would need to have something like the following in your schema: { type: Schema.Types.ObjectId, ref: 'collectionA' }
I am recently started working with GraphQL. I am able to fetch all the records from the database, but I want to get only limited records (like 10 at a time).
Any one please guide me to achieve this. Thanks
You'd pass the number of items to be returned as a parameter, and then use limit on MongoDB.
Type definition:
fields: () => {
posts: {
resolve: (root, params) => Post.find().limit(params.first)
}
}
Example query:
{
posts(first: 10) {
id
text
date
}
}