I'm practicing mongoDB with a small tweets dataset right now and don't have much experience with $graphLookup. For each document that matches, I'm trying to find the screen_name of the user the tweet is replying to, and if that tweet is also a retweet of another tweet, then display the user screen_name of that tweet too, so on and so forth up the hierarchy of retweets until the original tweet.
A standard document of retweets in the dataset looks like this
`
{
_id: ObjectId("5c8eccb0caa187d17ca62408"),
text: 'RT #Philanthropy: How should nonprofit groups measure their social-media efforts? A new podcast from #afine http://ht.ly/2yFlS',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:24 +0000 2010',
geo: null,
source: 'web',
retweeted_status: {
text: 'How should nonprofit groups measure their social-media efforts? A new podcast from #afine http://ht.ly/2yFlS',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:09:14 +0000 2010',
geo: null,
source: 'HootSuite',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [
{
indices: [ 83, 89 ],
screen_name: 'Afine',
name: 'Allison Fine',
id: 15016599
}
],
urls: [
{
indices: [ 90, 108 ],
url: 'http://ht.ly/2yFlS',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 2800,
profile_sidebar_fill_color: 'faf5eb',
location: 'Washington, D.C.',
verified: false,
follow_request_sent: null,
favourites_count: 2,
profile_sidebar_border_color: 'faf5eb',
profile_image_url: 'http://a2.twimg.com/profile_images/669725690/twitterprofilepic_normal.jpg',
geo_enabled: false,
created_at: 'Wed Dec 05 19:13:58 +0000 2007',
description: "The Chronicle of Philanthropy's official Twitter page, updated by Peter Panepento",
time_zone: 'Central Time (US & Canada)',
url: 'http://philanthropy.com',
screen_name: 'Philanthropy',
notifications: null,
profile_background_color: 'e7dfd3',
listed_count: 1679,
lang: 'en',
profile_background_image_url: 'http://a3.twimg.com/profile_background_images/71652755/bgv3.jpg',
statuses_count: 6492,
following: null,
profile_text_color: '572b0e',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'Philanthropy',
contributors_enabled: false,
profile_link_color: '246a88',
followers_count: 19406,
id: 10880202,
profile_use_background_image: true,
utc_offset: -21600
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819258393")
},
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [
{
indices: [ 3, 16 ],
screen_name: 'Philanthropy',
name: 'Philanthropy',
id: 10880202
},
{
indices: [ 101, 107 ],
screen_name: 'Afine',
name: 'Allison Fine',
id: 15016599
}
],
urls: [
{
indices: [ 108, 126 ],
url: 'http://ht.ly/2yFlS',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 68,
profile_sidebar_fill_color: 'e0ff92',
location: '',
verified: false,
follow_request_sent: null,
favourites_count: 0,
profile_sidebar_border_color: '87bc44',
profile_image_url: 'http://a1.twimg.com/profile_images/1101368689/3f84a22_normal.jpg',
geo_enabled: false,
created_at: 'Thu Jul 15 03:54:39 +0000 2010',
description: '',
time_zone: null,
url: null,
screen_name: 'DerekBechthold',
notifications: null,
profile_background_color: '9ae4e8',
listed_count: 1,
lang: 'en',
profile_background_image_url: 'http://s.twimg.com/a/1282328015/images/themes/theme1/bg.png',
statuses_count: 54,
following: null,
profile_text_color: '000000',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'Derek Bechthold',
contributors_enabled: false,
profile_link_color: '0000ff',
followers_count: 24,
id: 166846185,
profile_use_background_image: true,
utc_offset: null
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819398100")
},
{
_id: ObjectId("5c8eccb0caa187d17ca624ab"),
text: 'RT #ESPNsoccernet: Van der Vaart denies being a failure at Real Madrid: Rafael van der Vaart maintains he was no "failure" at Real Ma... ...',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:44 +0000 2010',
geo: null,
source: 'Twitter for iPhone',
retweeted_status: {
text: 'Van der Vaart denies being a failure at Real Madrid: Rafael van der Vaart maintains he was no "failure" at Real Ma... http://bit.com/9d3Gah',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 16:53:41 +0000 2010',
geo: null,
source: 'twitterfeed',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [],
urls: [
{
indices: [ 118, 138 ],
url: 'http://bit.com/9d3Gah',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 0,
profile_sidebar_fill_color: 'e0ff92',
location: null,
verified: false,
follow_request_sent: null,
favourites_count: 0,
profile_sidebar_border_color: '87bc44',
profile_image_url: 'http://a2.twimg.com/profile_images/70131430/espn_normal.jpg',
geo_enabled: false,
created_at: 'Wed Jan 07 15:27:26 +0000 2009',
description: null,
time_zone: null,
url: null,
screen_name: 'ESPNsoccernet',
notifications: null,
profile_background_color: '9ae4e8',
listed_count: 368,
lang: 'en',
profile_background_image_url: 'http://s.twimg.com/a/1282351897/images/themes/theme1/bg.png',
statuses_count: 13447,
following: null,
profile_text_color: '000000',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'ESPNsoccernet',
contributors_enabled: false,
profile_link_color: '0000ff',
followers_count: 4669,
id: 18724620,
profile_use_background_image: true,
utc_offset: null
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22814093566")
},
coordinates: null,
in_reply_to_screen_name: null,
truncated: true,
entities: {
user_mentions: [
{
indices: [ 3, 17 ],
screen_name: 'ESPNsoccernet',
name: 'ESPNsoccernet',
id: 18724620
}
],
urls: [],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 54,
profile_sidebar_fill_color: 'e0ff92',
location: 'Park Triangle Apartments (US)',
verified: false,
follow_request_sent: null,
favourites_count: 2,
profile_sidebar_border_color: '87bc44',
profile_image_url: 'http://a0.twimg.com/profile_images/1066211448/27399ece-83d9-4187-bf0d-04f538d7725c_normal.png',
geo_enabled: false,
created_at: 'Mon Apr 28 23:28:31 +0000 2008',
description: '',
time_zone: 'Quito',
url: null,
screen_name: 'desjef75',
notifications: null,
profile_background_color: '9ae4e8',
listed_count: 0,
lang: 'en',
profile_background_image_url: 'http://s.twimg.com/a/1283397887/images/themes/theme1/bg.png',
statuses_count: 1031,
following: null,
profile_text_color: '000000',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'desjef75',
contributors_enabled: false,
profile_link_color: '0000ff',
followers_count: 15,
id: 14577356,
profile_use_background_image: true,
utc_offset: -18000
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819419400")
}
`
This is the query I have so far
db.tweets.aggregate([{$graphLookup:{from: "tweets", startWith: "$text", connectFromField:"text", connectToField:"retweeted_status.text", as:"Retweets Hierarchy"}}])
But this isn't really showing the screen_name, I'm not really even sure how to that while still matching the text to the fields and I'm so lost any help would be much appreciated.
My ideal result would be something like the image below, where it would show a clear structure from the bottom up.
Related
A sample document with user mentions in the tweets dataset I'm working with looks like this. I'm trying to get mongoDB to link the user.screen_name with their mentions in other tweets, if there are any, and go further up the hierarchy if that tweet also mentions someone else.
{
_id: ObjectId("5c8eccb2caa187d17ca6b214"),
text: 'PROMO - Concorra a um Ipad por semana #sorteio Faça seu cadastro e envie seu login para #lepetitpromo RT pls..',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 19:30:31 +0000 2010',
geo: null,
source: 'web',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [
{
indices: [ 88, 101 ],
screen_name: 'lepetitpromo',
name: 'Le Petit Promo',
id: 116353452
}
],
urls: [],
hashtags: [ { text: 'sorteio', indices: [ 38, 46 ] } ]
},
retweeted: false,
place: null,
user: {
friends_count: 39464,
profile_sidebar_fill_color: 'A32247',
location: 'SP, Brasil',
verified: false,
follow_request_sent: null,
favourites_count: 546,
profile_sidebar_border_color: 'e69cd7',
profile_image_url: 'http://a1.twimg.com/profile_images/1112836301/30480_107192455999355_100001258033161_53885_3288503_n_normal.jpg',
geo_enabled: true,
created_at: 'Mon Feb 22 04:34:35 +0000 2010',
description: 'Promonauta ligada 24hs nas melhores ofertas, sorteios e novidades no TWITTER! - Site http://www.lepetitpromo.com.br - contato: lepetitpromo#gmail.com',
time_zone: 'Brasilia',
url: 'http://lepetitpromo.com.br',
screen_name: 'lepetitpromo',
notifications: null,
profile_background_color: '000000',
listed_count: 683,
lang: 'en',
profile_background_image_url: 'http://a3.twimg.com/profile_background_images/141124445/x5293307ec686ccde4688a7b20c51d5a.jpg',
statuses_count: 49358,
following: null,
profile_text_color: 'b393b3',
protected: false,
show_all_inline_media: false,
profile_background_tile: true,
name: 'Le Petit Promo',
contributors_enabled: false,
profile_link_color: '60a9d1',
followers_count: 57774,
id: 116353452,
profile_use_background_image: true,
utc_offset: -10800
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22824145700")
}
Here's the query I have so far:
db.tweets.aggregate(
[
{
$graphLookup: {
from: 'tweets',
startWith: "$user.screen_name",
connectFromField: 'user.screen_name',
connectToField: 'entities.user_mentions.screen_name',
as: 'User Mentions'
}
}
]
)
But the code above still doesn't return anything, I'm not really sure what I'm getting wrong but any help would be much appreciated.
I'm learning mongoDB and there's an exercise where we have to come up with our own scenario and make a query based on that description. Problem is I'm not really clear on what or how to use mapReduce effectively, so I created this aggregation query and hopefully someone can point me to a similar way I can do it but with mapReduce?
The dataset of tweets I'm working with looks generally looks like this:
{
_id: ObjectId("5c8eccb0caa187d17ca623fe"),
text: "#AdmireBiebs what ya think about to change my name to #NickJMunroC? I want one with them both. they're my imaginary husbands :P",
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:24 +0000 2010',
geo: null,
source: 'Power Twitter',
coordinates: null,
in_reply_to_screen_name: 'AdmireBiebs',
truncated: false,
entities: {
user_mentions: [
{
indices: [ 0, 12 ],
screen_name: 'AdmireBiebs',
name: 'with ari ♥',
id: 64392486
}
],
urls: [],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 82,
profile_sidebar_fill_color: 'FFFFFF',
location: 'Barcelona, S p a i n ',
verified: false,
follow_request_sent: null,
favourites_count: 3,
profile_sidebar_border_color: 'E5C4AC',
profile_image_url: 'http://a1.twimg.com/profile_images/1080450837/MileyIcon_normal.jpg',
geo_enabled: false,
created_at: 'Sun Aug 09 21:21:31 +0000 2009',
description: "I Support #nickjonas & #jonasbrothers 'til the end. NILEY FOR THE WIN. ",
time_zone: 'Greenland',
url: null,
screen_name: 'TheNickJCrew',
notifications: null,
profile_background_color: 'DAE8EB',
listed_count: 51,
lang: 'en',
profile_background_image_url: 'http://a3.twimg.com/profile_background_images/124098229/xa2b1612896a14878a1008db61390773.png',
statuses_count: 808,
following: null,
profile_text_color: 'ababab',
protected: false,
show_all_inline_media: false,
profile_background_tile: true,
name: 'Ariadna',
contributors_enabled: false,
profile_link_color: 'c4ad8f',
followers_count: 219,
id: 64257227,
profile_use_background_image: true,
utc_offset: -10800
},
favorited: false,
in_reply_to_user_id: 64392486,
id: Long("22819397900")
},
{
_id: ObjectId("5c8eccb0caa187d17ca62408"),
text: 'RT #Philanthropy: How should nonprofit groups measure their social-media efforts? A new podcast from #afine http://ht.ly/2yFlS',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:24 +0000 2010',
geo: null,
source: 'web',
retweeted_status: {
text: 'How should nonprofit groups measure their social-media efforts? A new podcast from #afine http://ht.ly/2yFlS',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:09:14 +0000 2010',
geo: null,
source: 'HootSuite',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [
{
indices: [ 83, 89 ],
screen_name: 'Afine',
name: 'Allison Fine',
id: 15016599
}
],
urls: [
{
indices: [ 90, 108 ],
url: 'http://ht.ly/2yFlS',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 2800,
profile_sidebar_fill_color: 'faf5eb',
location: 'Washington, D.C.',
verified: false,
follow_request_sent: null,
favourites_count: 2,
profile_sidebar_border_color: 'faf5eb',
profile_image_url: 'http://a2.twimg.com/profile_images/669725690/twitterprofilepic_normal.jpg',
geo_enabled: false,
created_at: 'Wed Dec 05 19:13:58 +0000 2007',
description: "The Chronicle of Philanthropy's official Twitter page, updated by Peter Panepento",
time_zone: 'Central Time (US & Canada)',
url: 'http://philanthropy.com',
screen_name: 'Philanthropy',
notifications: null,
profile_background_color: 'e7dfd3',
listed_count: 1679,
lang: 'en',
profile_background_image_url: 'http://a3.twimg.com/profile_background_images/71652755/bgv3.jpg',
statuses_count: 6492,
following: null,
profile_text_color: '572b0e',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'Philanthropy',
contributors_enabled: false,
profile_link_color: '246a88',
followers_count: 19406,
id: 10880202,
profile_use_background_image: true,
utc_offset: -21600
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819258393")
},
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [
{
indices: [ 3, 16 ],
screen_name: 'Philanthropy',
name: 'Philanthropy',
id: 10880202
},
{
indices: [ 101, 107 ],
screen_name: 'Afine',
name: 'Allison Fine',
id: 15016599
}
],
urls: [
{
indices: [ 108, 126 ],
url: 'http://ht.ly/2yFlS',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 68,
profile_sidebar_fill_color: 'e0ff92',
location: '',
verified: false,
follow_request_sent: null,
favourites_count: 0,
profile_sidebar_border_color: '87bc44',
profile_image_url: 'http://a1.twimg.com/profile_images/1101368689/3f84a22_normal.jpg',
geo_enabled: false,
created_at: 'Thu Jul 15 03:54:39 +0000 2010',
description: '',
time_zone: null,
url: null,
screen_name: 'DerekBechthold',
notifications: null,
profile_background_color: '9ae4e8',
listed_count: 1,
lang: 'en',
profile_background_image_url: 'http://s.twimg.com/a/1282328015/images/themes/theme1/bg.png',
statuses_count: 54,
following: null,
profile_text_color: '000000',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'Derek Bechthold',
contributors_enabled: false,
profile_link_color: '0000ff',
followers_count: 24,
id: 166846185,
profile_use_background_image: true,
utc_offset: null
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819398100")
},
{
_id: ObjectId("5c8eccb0caa187d17ca62415"),
text: 'Photo: porque nada se compara com o simples fato de ser feliz . http://tumblr.com/xhxhfo113',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:27 +0000 2010',
geo: null,
source: 'Tumblr',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: {
user_mentions: [],
urls: [
{
indices: [ 64, 91 ],
url: 'http://tumblr.com/xhxhfo113',
expanded_url: null
}
],
hashtags: []
},
retweeted: false,
place: null,
user: {
friends_count: 379,
profile_sidebar_fill_color: 'f7e8f3',
location: 'rio de janeiro',
verified: false,
follow_request_sent: null,
favourites_count: 6,
profile_sidebar_border_color: 'd69fc8',
profile_image_url: 'http://a1.twimg.com/profile_images/1039533261/a_normal.JPG',
geo_enabled: false,
created_at: 'Wed Jun 30 17:03:39 +0000 2010',
description: '',
time_zone: 'Brasilia',
url: 'http://twitpic.com/photos/amanda_raibolt',
screen_name: 'amanda_raibolt',
notifications: null,
profile_background_color: 'fcfcfc',
listed_count: 2,
lang: 'en',
profile_background_image_url: 'http://a3.twimg.com/profile_background_images/118456393/2.jpg',
statuses_count: 562,
following: null,
profile_text_color: 'f771b4',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: 'Raibolt Amanda ! ',
contributors_enabled: false,
profile_link_color: 'c95799',
followers_count: 86,
id: 161359013,
profile_use_background_image: true,
utc_offset: -10800
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819400700")
},
{
_id: ObjectId("5c8eccb0caa187d17ca62419"),
text: 'えっ?',
in_reply_to_status_id: null,
retweet_count: null,
contributors: null,
created_at: 'Thu Sep 02 18:11:27 +0000 2010',
geo: null,
source: 'twittbot.net',
coordinates: null,
in_reply_to_screen_name: null,
truncated: false,
entities: { user_mentions: [], urls: [], hashtags: [] },
retweeted: false,
place: null,
user: {
friends_count: 27,
profile_sidebar_fill_color: 'e0ff92',
location: '東京湾',
verified: false,
follow_request_sent: null,
favourites_count: 0,
profile_sidebar_border_color: '87bc44',
profile_image_url: 'http://a2.twimg.com/profile_images/1013384238/___________normal.jpg',
geo_enabled: false,
created_at: 'Tue Jun 22 09:10:16 +0000 2010',
description: '海老天こと東風(ID:lobster090)のBOTです。\r\nたまに海老天/A.B.十/東風でつぶやいてきやがります。',
time_zone: 'Hawaii',
url: null,
screen_name: 'lobster090_bot',
notifications: null,
profile_background_color: '9ae4e8',
listed_count: 1,
lang: 'ja',
profile_background_image_url: 'http://s.twimg.com/a/1281738360/images/themes/theme1/bg.png',
statuses_count: 1569,
following: null,
profile_text_color: '000000',
protected: false,
show_all_inline_media: false,
profile_background_tile: false,
name: '海老bot',
contributors_enabled: false,
profile_link_color: '0000ff',
followers_count: 19,
id: 158301291,
profile_use_background_image: true,
utc_offset: -36000
},
favorited: false,
in_reply_to_user_id: null,
id: Long("22819401300")
And this is the aggregation query I have that basically looks at the user.screen_name of each tweet and count how many times each user tweets in the whole dataset, and sort that based on amount of tweets.
db.tweets.aggregate([{$group: {_id: "$user.screen_name", totalTweets: {$count: {}}}}, {$sort: {totalTweets: -1}}])
And the output looks like this
{ _id: 'JBTeenageDream', totalTweets: 6 },
{ _id: 'Jobs_SanAntonio', totalTweets: 6 },
{ _id: 'vslxo', totalTweets: 5 },
{ _id: 'mysterytrick', totalTweets: 4 },
{ _id: 'djmangueira', totalTweets: 4 },
{ _id: 'JPguedas', totalTweets: 4 }
So what's a way to do that but with mapReduce?
I am having code like this
const aggregate = [];
const lookup = {
$lookup: {
from: "balances",
localField: "accountNumber",
foreignField: "account_id",
as: "bankbalance",
},
};
const unwind = {
$unwind: "$bankbalance",
};
const match = {
$match: {
"bankbalance.date": {
$gte: startDate,
$lte: endDate,
},
userId: mongoose.Types.ObjectId(userId),
isActive: 1,
type: "accountType"
},
};
const group = {
$group: {
_id: '$_id',
accountNumber:{"$first":"$accountNumber"},
balances: {
$addToSet: { date: "$$ROOT.date", amount: "$$ROOT.amount" },
},
},
};
aggregate.push(lookup);
aggregate.push(unwind);
aggregate.push(group);
aggregate.push(match);
let data = await BankAccounts.aggregate(aggregate);
this code is giving me empty [] data, if I do not use $group then its giving data like this
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: {
_id: 61262b9bf9649b2c6fe7d67c,
ISODate: '2021-05-19T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1047.62,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-19',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
},
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: {
_id: 61262b99f9649b2c6fe7d671,
ISODate: '2021-05-24T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1137.02,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-24',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
}
this is giving all data record again and again, here reference between 2 collection is accountNumber and account_id. I want to group all records in 1 like
{
_id: 611bc2c4f9649b2c6fe4007f,
bankId: 'string',
mask: '0000',
name: 'Plaid Checking',
userId: 611bc2794d9f391bf2cd7877,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
bankTokenId: xxxxxxxxxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-17T14:08:04.058Z,
isConnected: true,
subtype: 'checking',
type: 'depository',
updatedAt: 2021-08-25T11:36:37.824Z,
isActive: 1,
bankbalance: [{
_id: 61262b99f9649b2c6fe7d671,
ISODate: '2021-05-24T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1137.02,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-24',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
},
{
_id: 61262b9bf9649b2c6fe7d67c,
ISODate: '2021-05-19T00:00:00.000Z',
account_id: 'xxxxxxxxxxxxxxxxxxxxxxxx',
userId: 611bc2794d9f391bf2cd7877,
ISOCountryCode: null,
accountId: xxxxxxxxxxxxxxxxxxxx,
amount: -1047.62,
bankTokenId: xxxxxxxxxxxxxxxxxxxx,
createdAt: 2021-08-25T11:37:26.960Z,
current: null,
date: '2021-05-19',
institutionId: xxxxxxxxxxxxxxxxxxxxxx,
isActive: 1,
unofficialCountryCode: null,
updatedAt: 2021-08-25T11:37:26.960Z
}
]
}
also sort bankbalance by date. Any help! Thanks in advance!!
The stages are in the order
aggregate.push(lookup);
aggregate.push(unwind);
aggregate.push(group);
aggregate.push(match);
When the group stage executes, each document will have only the fields noted in that stage. i.e.
{
_id: 611bc2c4f9649b2c6fe4007f,
accountNumber: 'xxxxxxxxxxxxxxxxxxx',
balances: [ {date: ......, amount: .....} ]
}
When the match stage executes, the fields "bankbalance.date", userId, isActive, and type don't exist, so no documents satisfy the match.
i am triying to connect MongoDB with the NextJS API route Apollo example:
https://github.com/vercel/next.js/blob/canary/examples/api-routes-apollo-server-and-client
I cannot find any official doc. So i follow this topic:
Connect Apollo with mongodb
The idea is to connect Mongodb from the context of ApolloServer
pages/api/graphql.js
import { ApolloServer } from 'apollo-server-micro';
import { schema } from '../../apollo/schema';
import { connectToDatabase } from '../../utils/mongodb';
const apolloServer = new ApolloServer({
schema,
context: async () => {
const { db } = await connectToDatabase();
return { db };
},
});
export const config = {
api: {
bodyParser: false,
},
};
export default apolloServer.createHandler({ path: '/api/graphql' });
the "connectToDatabase" is coming from the example "with-mongo"
https://github.com/vercel/next.js/blob/canary/examples/with-mongodb/util/mongodb.js
There is 3 ways of rendering pages in NextJS. When i connect my db like so (inside the ApolloServer context) it works just fine with the client side rendering but not at all with the Static and Server Side Rendering. The context inside my resolver function is undefined.
apollo/resolvers.js
export const resolvers = {
Query: {
async getAllCards(_parent, _args, _context, _info) {
console.log('_context resolver :>> ', _context);
const res = await _context.db.db
.collection('cards')
.find({})
.limit(20)
.toArray();
console.log('res :>> ', res);
return res;
},
},
};
At that point i tried to follow this topic
Next.js graphql context is empty {} on SSR getServerSideProps
Following thoses steps i am ending with 2 files modified:
pages/api/graphql
import { ApolloServer } from 'apollo-server-micro';
import { schema } from '../../apollo/schema';
import { connectToDatabase } from '../../utils/mongodb';
async function contextResolver(ctx) {
ctx.db = await connectToDatabase();
return ctx;
}
const apolloServer = new ApolloServer({
schema,
context: contextResolver,
});
export const config = {
api: {
bodyParser: false,
},
};
export default apolloServer.createHandler({ path: '/api/graphql' });
and
pages/explore_SSR.js
import gql from 'graphql-tag';
import Link from 'next/link';
import { initializeApollo } from '../apollo/client';
import { connectToDatabase } from '../utils/mongodb';
const Explore = () => {
return (
// UI Stuff
)
}
export async function getServerSideProps(ctx) {
console.log('ctx :>> ', ctx);
async function contextResolver(ctx) {
ctx.db = await connectToDatabase();
return ctx;
}
await contextResolver(ctx);
console.log('ctx after :>> ', ctx);
const apolloClient = initializeApollo(null, ctx);
await apolloClient.query({
query: gql`
query GetAllMementoQuery {
getAllMemento {
title
}
}
`,
});
return {
props: {
props: { initialApolloState: apolloClient.cache.extract() },
},
};
}
export default Explore;
result of the console.log: console.log('ctx after :>> ', ctx);
ctx after :>> {
req: IncomingMessage {
_readableState: ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: [],
flowing: null,
ended: true,
endEmitted: false,
reading: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
errorEmitted: false,
emitClose: true,
autoDestroy: false,
destroyed: false,
errored: null,
closed: false,
closeEmitted: false,
defaultEncoding: 'utf8',
awaitDrainWriters: null,
multiAwaitDrain: false,
readingMore: true,
decoder: null,
encoding: null,
[Symbol(kPaused)]: null
},
_events: [Object: null prototype] { end: [Function: clearRequestTimeout] },
_eventsCount: 1,
_maxListeners: undefined,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
parser: [HTTPParser],
on: [Function: socketListenerWrap],
addListener: [Function: socketListenerWrap],
prependListener: [Function: socketListenerWrap],
_paused: false,
_httpMessage: [ServerResponse],
timeout: 0,
[Symbol(async_id_symbol)]: 285916,
[Symbol(kHandle)]: [TCP],
[Symbol(kSetNoDelay)]: false,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 24100466,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: false,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 290206,
[Symbol(triggerId)]: 290203
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(RequestTimeout)]: undefined
},
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: {
host: 'localhost:3000',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0',
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'accept-language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
'accept-encoding': 'gzip, deflate',
referer: 'http://localhost:3000/explore_clientSide',
dnt: '1',
connection: 'keep-alive',
'upgrade-insecure-requests': '1',
'sec-gpc': '1'
},
rawHeaders: [
'Host',
'localhost:3000',
'User-Agent',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:88.0) Gecko/20100101 Firefox/88.0',
'Accept',
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language',
'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding',
'gzip, deflate',
'Referer',
'http://localhost:3000/explore_clientSide',
'DNT',
'1',
'Connection',
'keep-alive',
'Upgrade-Insecure-Requests',
'1',
'Sec-GPC',
'1'
],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '/explore_SSR',
method: 'GET',
statusCode: null,
statusMessage: null,
client: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
parser: [HTTPParser],
on: [Function: socketListenerWrap],
addListener: [Function: socketListenerWrap],
prependListener: [Function: socketListenerWrap],
_paused: false,
_httpMessage: [ServerResponse],
timeout: 0,
[Symbol(async_id_symbol)]: 285916,
[Symbol(kHandle)]: [TCP],
[Symbol(kSetNoDelay)]: false,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 24100466,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: false,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 290206,
[Symbol(triggerId)]: 290203
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(RequestTimeout)]: undefined
},
_consuming: false,
_dumped: false,
cookies: [Getter/Setter],
__NEXT_INIT_QUERY: {},
[Symbol(kCapture)]: false,
[Symbol(RequestTimeout)]: undefined
},
res: <ref *1> ServerResponse {
_events: [Object: null prototype] { finish: [Function: bound resOnFinish] },
_eventsCount: 1,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: true,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: false,
_headerSent: false,
socket: Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: null,
_readableState: [ReadableState],
_events: [Object: null prototype],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
parser: [HTTPParser],
on: [Function: socketListenerWrap],
addListener: [Function: socketListenerWrap],
prependListener: [Function: socketListenerWrap],
_paused: false,
_httpMessage: [Circular *1],
timeout: 0,
[Symbol(async_id_symbol)]: 285916,
[Symbol(kHandle)]: [TCP],
[Symbol(kSetNoDelay)]: false,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]: Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 24100466,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
[Symbol(refed)]: false,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 290206,
[Symbol(triggerId)]: 290203
},
[Symbol(kBuffer)]: null,
[Symbol(kBufferCb)]: null,
[Symbol(kBufferGen)]: null,
[Symbol(kCapture)]: false,
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0,
[Symbol(RequestTimeout)]: undefined
},
_header: null,
_keepAliveTimeout: 5000,
_onPendingData: [Function: bound updateOutgoingData],
_sent100: false,
_expect_continue: false,
statusCode: 200,
flush: [Function: flush],
write: [Function: write],
end: [Function: end],
on: [Function: on],
writeHead: [Function: writeHead],
[Symbol(kCapture)]: false,
[Symbol(kNeedDrain)]: false,
[Symbol(corked)]: 0,
[Symbol(kOutHeaders)]: null
},
query: {},
resolvedUrl: '/explore_SSR',
locales: undefined,
locale: undefined,
defaultLocale: undefined,
db: {
client: MongoClient {
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
s: [Object],
topology: [NativeTopology],
[Symbol(kCapture)]: false
},
db: Db {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
s: [Object],
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter],
[Symbol(kCapture)]: false
}
}
}
But it's not working for me. The _context of my resolver is still undefined.
(console.log in apollo/resolvers.js: _context :>> undefined)
Maybe we cannot use Apollo and Database connection with the API route and Server side rendering mode or i just missing something big.
Any idea of how i could implement the Mongodb database connection to have acces to it from my resolver in any kind of rendering mode?
I managed to upload an image to facebook using online URL but, when I try a local image using format file://path/to/imageI get the error
{"error":{"message":"(#100) url should represent a valid URL","type":"OAuthException","code":100}
is it doable ? or am doing it wrong ?
async function upload_fb_image(photo) {
return new Promise(resolve => {
FB.api(PAGE_ID + '/photos', 'post', {
message: 'Message',
url: LINK_TO_IMAGE,
published: false,
caption: 'Ad',
access_token: EXD_ACCESS_TOKEN
}).then(data => { resolve(data) })
})
}
as Form data
I tried as form data as mentioned in answers ... I receive ok response but, the image ID is not returned, I get the below JSON in reponse
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]:
{ body:
PassThrough {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: [Object], tail: [Object], length: 1 },
length: 25,
pipes: null,
pipesCount: 0,
flowing: null,
ended: true,
endEmitted: false,
reading: false,
sync: false,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
paused: true,
emitClose: true,
autoDestroy: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
_events:
[Object: null prototype] {
prefinish:
{ [Function: prefinish]
[length]: 0,
[name]: 'prefinish',
[prototype]: prefinish { [constructor]: [Circular] } },
error:
{ [Function]
[length]: 1,
[name]: '',
[prototype]: { [constructor]: [Circular] } } },
_eventsCount: 2,
_maxListeners: undefined,
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: false,
ending: true,
ended: true,
finished: true,
destroyed: false,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite:
{ [Function: bound onwrite] [length]: 1, [name]: 'bound onwrite' },
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 0,
prefinished: true,
errorEmitted: false,
emitClose: true,
autoDestroy: false,
bufferedRequestCount: 0,
corkedRequestsFree:
{ next: null,
entry: null,
finish:
{ [Function: bound onCorkedFinish] [length]: 1, [name]: 'bound onCorkedFinish' } } },
writable: false,
allowHalfOpen: true,
_transformState:
{ afterTransform:
{ [Function: bound afterTransform] [length]: 2, [name]: 'bound afterTransform' },
needTransform: false,
transforming: false,
writecb: null,
writechunk: null,
writeencoding: 'buffer' } },
disturbed: false,
error: null },
[Symbol(Response internals)]:
{ url: 'https://graph.facebook.com/page_id/photos',
status: 200,
statusText: 'OK',
headers:
Headers {
[Symbol(map)]:
[Object: null prototype] {
'x-business-use-case-usage':
[ '{"1006471116044666":[{"type":"pages","call_count":1,"total_cputime":1,"total_time":1,"estimated_time_to_regain_access":0}]}',
[length]: 1 ],
'content-type': [ 'application/json; charset=UTF-8', [length]: 1 ],
'facebook-api-version': [ 'v2.10', [length]: 1 ],
'strict-transport-security': [ 'max-age=15552000; preload', [length]: 1 ],
pragma: [ 'no-cache', [length]: 1 ],
'x-fb-rev': [ '1001316471', [length]: 1 ],
'access-control-allow-origin': [ '*', [length]: 1 ],
'cache-control':
[ 'private, no-cache, no-store, must-revalidate', [length]: 1 ],
'x-fb-trace-id': [ 'CSSaQru0iZZ', [length]: 1 ],
'x-fb-request-id': [ 'AguAWIpbfPySfVvwPjZZBec', [length]: 1 ],
expires: [ 'Sat, 01 Jan 2000 00:00:00 GMT', [length]: 1 ],
'x-fb-debug':
[ 'NnSTSun7s8VUcMnXu9cUYXQh/7laST0pILTNbAJrS0mtGHGXnQt17fRtyhS8R+RkZWyawJ4meKDWNKT1N+1uBA==',
[length]: 1 ],
date: [ 'Sat, 19 Oct 2019 01:31:32 GMT', [length]: 1 ],
'x-fb-trip-id': [ '1886706526', [length]: 1 ],
'alt-svc': [ 'h3-23=":443"; ma=3600', [length]: 1 ],
connection: [ 'close', [length]: 1 ],
'content-length': [ '25', [length]: 1 ] } },
counter: 0 } }
The url must be a public url, not some url from your local computer. Alternatively, you can use FormData:
const fileReader = new FileReader();
const file = document.getElementById('imageInput').files[0];
fileReader.onloadend = async () => {
const photoData = new Blob([fileReader.result], {type: 'image/jpg'});
const formData = new FormData();
formData.append('access_token', pageAccessToken);
formData.append('source', photoData);
formData.append('message', 'some status message');
let response = await fetch(`https://graph.facebook.com/${pageId}/photos`, {
body: formData,
method: 'post'
});
response = await response.json();
console.log(response);
};
fileReader.readAsArrayBuffer(file);
Source: https://www.devils-heaven.com/facebook-javascript-sdk-photo-upload-with-formdata/
finally it was solved using the below method
const formData = {
access_token: EXD_ACCESS_TOKEN,
source: fs.createReadStream("path/to/image"),
published: 'false'
}
console.log('sendning request')
request.post({ url: `https://graph.facebook.com/${PAGE_ID}/photos`, formData: formData }, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
resolve(body)
});