Not able to query for nested relations using dgraph-orm - node.js

I am using dgraph-orm for fetching nested relational values but it works for single level but not multiple level.
I am getting the page details but unable to fetch the avatar of the page.
Here is my snippet:
let posts = await PagePost.has('page_id', {
filter: {
page_id: {
uid_in: [page_id]
}
},
include: {
page_id: {
as: 'page',
include: {
avatar: {
as: 'avatar'
}
}
},
owner_id: {
as: 'postedBy'
}
},
order: [], // accepts order like the above example
first: perPage, // accepts first
offset: offset, // accepts offset
});
I am not getting avatar for the attribute page_id:
{
"uid": "0x75b4",
"title": "",
"content": "haha",
"created_at": "2019-09-23T08:50:52.957Z",
"status": true,
"page": [
{
"uid": "0x75ac",
"name": "Saregamaapaaaa...",
"description": "This a is place where you can listen ti thrilling music.",
"created_at": "2019-09-23T06:46:50.756Z",
"status": true
}
],
"postedBy": [
{
"uid": "0x3",
"first_name": "Mohit",
"last_name": "Talwar",
"created_at": "2019-07-11T11:37:33.853Z",
"status": true
}
]
}
Is there a support for multilevel field querying in the orm??

There was some issue with ORM itself it was not able to recognize the correct model name for multilevel includes and generating the wrong queries.
Fixed the same in version 1.2.4, please run npm update dgraph-orm --save to update your DgraphORM.
Thanks for the issue.

Related

Order result resolved via resolver in graphql + apollo server + nodejs

I am trying to order an array returned by resolver in GraphQL.
I can only think of way of ordering data using DB Query, but how can we order data that GraphQL resolves using its resolver functions?
Below is my Query resolver:
getAllNotifications: (
_parent,
_args: { authorId: string },
context: Context
) => {
return context.prisma.blog.findMany({
where: {
authorId: _args.authorId,
},
orderBy: {
created_at: "desc",
},
});
},
And my query:
query Query($authorId: String) {
getAllNotifications(authorId: $authorId) {
title
comment {
id
created_at
}
}
}
And result:
{
"data": {
"getAllNotifications": [
{
"title": "First Ride! ",
"comment": [ <--- I am trying to order this comment array using created_at date
{
"id": "cl8afqaqx001209jtxx7mt5h6",
"created_at": "2022-09-20T16:53:07.689Z"
},
{
"id": "cl8agiq71001509l27or7oxyd",
"created_at": "2022-09-20T17:15:14.077Z"
},
{
"id": "cl8ahmvrm003109l8dp684bn6",
"created_at": "2022-09-20T17:46:27.538Z"
},
{
"id": "cl99kj24p002609iajdbpycg0",
"created_at": "2022-10-15T06:59:24.169Z"
}
]
}
]
}
}
I didn't found anything in Graphql docs regarding ordering data returned by resolver
GraphQL doesn't have functions for selection and ordering, those are jobs that resolvers must do.
Add a resolver for comment that sorts the comment array. Your existing sort just sorts based on the created_at date of the post.

Remove object from nested array in MongoDB using NodeJS

I can see that this question should have been answered here, but the code simply doesn't work for me (I have tried multiple, similar variations).
Here is my data:
[{
"_id": {
"$oid": "628cadf43a2fd997be8ce242"
},
"dcm": 2,
"status": true,
"comments": [
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 1"
},
{
"id": 289733,
"dcm": 2,
"status": true,
"clock": "158",
"user": "Nathan Field",
"dept": "IT",
"department": [],
"dueback": "",
"comment": "test 2"
}
],
"department": [],
"dueback": ""
}]
And here is my code
const deleteResult = await db.collection('status').updateOne(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ upsert: false },
{ multi: true }
);
Absolutely nothing happens...
So the issue ended up being something to do with running multiple update operations within one function. I have a database connection function like this:
const withDB = async (operations, res) => {
try {
const client = await MongoClient.connect('mongodb://localhost:27017', { useNewUrlParser: true });
const db = client.db('collection');
await operations(db);
client.close();
} catch (error) {
res.status(500).json({ message: 'Error connecting to db', error });
}
}
And then I call this by using:
withDB(async (db) => {
await db.collection('status').updateMany(
{ "dcm": comments.dcm },
{ $pull: { "comments": { "id": comments.id } } },
{ multi: true }
);
});
The issue occurred it would seem because I had two of these update operations within one withDB function. I have multiple operations in other instances (update item, then fetch collection), but for some reason this caused an issue.
I created a separate call to the withDB function to perform the '$pull' (delete) request, and then updated the array with the new comments.
To check that there was nothing wrong with my actual query, I used Studio3T's IntelliShell feature. If I'd done that sooner I would saved myself a lot of time!

MongoDb find all objects that contain nested value

This is my user object sent as token in req:
{
"_id": "6212aba16653621e67393549c",
"name": "User",
"email": "user#gmail.com",
"__v": 0
}
This is my get function code:
const getSharedLists = asyncHandler(async (req, res) => {
const lists = await List.find({
sharedWith: { email: req.user.email },
});
res.status(200).json(lists);
});
This is what object looks like:
{
"_id": "621817233300dfff68e23710",
"user": "6212ab33383621e67393549c",
"listName": "test update",
"private": true,
"items": [
{
"itemName": "Bananas",
"quantity": 3,
"isBought": false,
"isle": "isle",
"_id": "621b043622147906eece2e72"
},
],
"sharedWith": [
{
"email": "user#gmail.com",
"_id": "621bdbf0791a322534284c49"
}
],
"createdAt": "2022-02-24T23:39:25.668Z",
"updatedAt": "2022-02-27T21:21:03.584Z",
"__v": 0,
},
I keep getting empty array back, even when hard code req.user.email as "user#gmail.com" for example. I need to find all lists on MongoDb that have my email in array of sharedWith.
Can somebody help please. Apparently I'm using List.find method wrong but can't seem to figure out the syntax.
You need (.) dot notation.
const lists = await List.find({
"sharedWith.email" : req.user.email
});
Sample Mongo Playground
Reference
Specify a Query Condition on a Field Embedded in an Array of Documents

How to update a value inside mongodb with nodeJS?

I'm trying to update a value inside mogoodb array but is the problem
database?
"TempChannels": [{
"user": "299481590445113345",
"channel": "794869948878159884",
"settings": []
}, {
"user": "583363766750806043",
"channel": "795004103998308352",
"settings": []
}],
The part of the code that should update the user:
Data.TempChannels[0].user = Target.id
Data.save().catch(er => console.log(er))
Also, no error appears when I run the code. and when i console the data it returns a user which has updated but it is not actually saved in mongodb!
code
Data.save().then(() => console.log(Data.TempChannels[0].user))
this is the whole data
{
"_id": {
"$oid": "5ff0cd1ee3d9fd2d40d82d23"
},
"TempChannels": [{
"user": "299481590445113345",
"channel": "795014692522295326",
"settings": []
}, {
"user": "583363766750806043",
"channel": "795015273060892753",
"settings": []
}],
"Guild": "704158258201624657",
"Stats": "true",
"ChannelID": "795014681664290826",
"ParentID": "795014680556994610",
"LogChannelID": "795014683601010709",
"TempControlChannelID": "795014682518749274",
"DefaultSettings": {
"limit": null,
"name": null,
"bitrate": null,
"copyperms": null
},
"__v": 2
}
I'm filtering the data by Guild
if you are using mongoose to connect MongoDB, the
Use markModified("updated field name")
Data.TempChannels[0].user = Target.id
Data.markModified('TempChannels');
Data.save().catch(er => console.log(er))
if you are using mongoose, there is a method that will allow to update the content of existing data
const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
res.n; // Number of documents matched
res.nModified; // Number of documents modified
If you are using Mongoose, you can update the record by doing something similar to this:
SchemaName.update({Guild: 'Guild Value Here'}, {$set: { "TempChannels[0].user" : "%newvalue%"}})
.then((data) => {
console.log(data)
})
.catch(err => {
console.log.error(err);
});
You should replace schemaName with the name of your schema if you are using mongoose, and in case you are not using it, I think it would be better for you to start using it.

MongoDB: Query model and check if document contains object or not, then mark / group result

I have a Model called Post, witch contains an property array with user-ids for users that have liked this post.
Now, i need to query the post model, and mark the returned results with likedBySelf true/false for use in by client - is this possible?
I dont have to store the likedBySelf property in the database, just modify the results to have that property.
A temporary solution i found was to do 2 queries, one that finds the posts that is liked by user x, and the ones that have not been liked by user x, and en map (setting likedBySelf true/false) and combine the 2 arrays and return the combined array. But this gives some limitations to other query functions such as limit and skip.
So now my queries looks like this:
var notLikedByQuery = Post.find({likedBy: {$ne: req.body.user._id}})
var likedByQuery = Post.find({likedBy: req.body.user._id})
(I'm using the Mongoose lib)
PS. A typical post can look like this (JSON):
{
"_id": {
"$oid": "55fc463c83b2d2501f563544"
},
"__t": "Post",
"groupId": {
"$oid": "55fc463c83b2d2501f563545"
},
"inactiveAfter": {
"$date": "2015-09-25T17:13:32.426Z"
},
"imageUrl": "https://hootappprodstorage.blob.core.windows.net/devphotos/55fc463b83b2d2501f563543.jpeg",
"createdBy": {
"$oid": "55c49e2d40b3b5b80cbe9a03"
},
"inactive": false,
"recentComments": [],
"likes": 8,
"likedBy": [
{
"$oid": "558b2ce70553f7e807f636c7"
},
{
"$oid": "559e8573ed7c830c0a677c36"
},
{
"$oid": "559e85bced7c830c0a677c43"
},
{
"$oid": "559e854bed7c830c0a677c32"
},
{
"$oid": "559e85abed7c830c0a677c40"
},
{
"$oid": "55911104be2f86e81d0fb573"
},
{
"$oid": "559e858fed7c830c0a677c3b"
},
{
"$oid": "559e8586ed7c830c0a677c3a"
}
],
"location": {
"type": "Point",
"coordinates": [
10.01941398718396,
60.96738099591897
]
},
"updatedAt": {
"$date": "2015-09-22T08:45:41.480Z"
},
"createdAt": {
"$date": "2015-09-18T17:13:32.426Z"
},
"__v": 8
}
#tskippe you can use a method like following to process whether the post is liked by the user himself and call the function anywhere you want.
var processIsLiked = function(postId, userId, doc, next){
var q = Post.find({post_id: postId});
q.lean().exec(function(err,res){
if(err) return utils.handleErr(err, res);
else {
if(_.find(doc.post.likedBy,userId)){ //if LikedBy array contains the user
doc.post.isLiked = true;
} else {
doc.post.isLiked = false;
}
});
next(doc);
}
});
}
Because you are using q.lean() you dont need to actually persist the data. You need to just process it , add isLiked field in the post and send back the response. **note that we are manuplating doc directly. Also you chan tweek it to accept doc containing array of posts and iterating it and attach an isLiked field to each post.
I found that MongoDB's aggregation with $project tequnique was my best bet. So i wrote up an aggregation like this.
Explanation:
Since i want to keep the entire document, but $project purpose is to modify the docs, thus you have to specify the properties you want to keep. A simple way of keeping all the properties is to use "$$ROOT".
So i define a $project, set all my original properties to doc: "$$ROOT", then create a new property "likedBySelf", which is marked true / false if a specified USERID is in the $likedBy set.
I think that this is more clean and simple, than querying every single model after a query to set a likedBySelf flag. It may not be faster, but its cleaner.
Model.aggregate([
{ $project: {
doc: "$$ROOT",
likedBySelf: {
$cond: {
"if": { "$setIsSubset": [
[USERID],
"$likedBy"
]},
"then": true,
"else": false
}
}
}}
]);

Resources