Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GraphQL queries for find_groups() #128

Merged
merged 10 commits into from
Dec 30, 2021
135 changes: 105 additions & 30 deletions R/graphql.R
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ capture_str <- function(x) {
)
}


graphql_query <- function(graphql_file, ..., extra_graphql = NULL) {
graphql_file <- function(graphql_file, ..., extra_graphql = NULL) {
# inspiration: https://github.com/tidyverse/tidyversedashboard/blob/2c6cf9ebe8da938c35f6e9fc184c3b30265f1082/R/utils.R#L2
file <- system.file(file.path("graphql", paste0(graphql_file, ".graphql")), package = "meetupr")
query <- readChar(file, file.info(file)$size)
Expand All @@ -31,8 +30,11 @@ graphql_query <- function(graphql_file, ..., extra_graphql = NULL) {
}
query <- glue::glue_data(list(extra_graphql = extra_graphql), query, .open = "<<", .close = ">>", trim = FALSE)

graphql_query(query, ...)
}
graphql_query <- function(query, ...) {
variables <- purrr::compact(rlang::list2(...))
if (!rlang::is_named(variables)) {
if (length(variables) > 0 && !rlang::is_named(variables)) {
stop("Stop all GraphQL variables must be named. Variables:\n", capture_str(variables), call. = FALSE)
}
# str(variables)
Expand Down Expand Up @@ -75,14 +77,16 @@ graphql_query_generator <- function(
graphql_file,
cursor_fn,
extract_fn,
combiner_fn,
total_fn,
combiner_fn
pb_format = "[:bar] :current/:total :eta"
) {
force(graphql_file)
force(cursor_fn)
force(extract_fn)
force(total_fn)
force(combiner_fn)
force(pb_format)

function(
...
Expand All @@ -92,13 +96,13 @@ graphql_query_generator <- function(
pb <- NULL
while (TRUE) {
# browser()
graphql_res <- graphql_query(graphql_file, ..., !!!cursors)
graphql_res <- graphql_file(graphql_file, ..., !!!cursors)
cursors <- cursor_fn(graphql_res)
graphql_content <- extract_fn(graphql_res)
if (is.null(pb)) {
pb <- progress::progress_bar$new(
total = total_fn(graphql_res),
format = paste0(graphql_file, " [:bar] :current/:total :eta")
format = paste0(graphql_file, " ", pb_format)
)
on.exit({
# Make sure the pb is closed when exiting
Expand Down Expand Up @@ -126,10 +130,11 @@ gql_health_check <- graphql_query_generator(
extract_fn = function(x) {
x$data$healthCheck
},
combiner_fn = append,
total_fn = function(x) {
1
},
combiner_fn = append
pb_format = ":current/:total"
)

# gql_single_event <- graphql_query_generator(
Expand All @@ -155,8 +160,8 @@ gql_health_check <- graphql_query_generator(

gql_single_event <- graphql_query_generator(
"single_event",
cursor_fn = function(response) {
groupByUrlname <- response$data$groupByUrlname
cursor_fn = function(x) {
groupByUrlname <- x$data$groupByUrlname
unifiedEventsInfo <- groupByUrlname$unifiedEvents$pageInfo
upcomingEventsInfo <- groupByUrlname$upcomingEvents$pageInfo
pastEventsInfo <- groupByUrlname$pastEvents$pageInfo
Expand Down Expand Up @@ -212,6 +217,7 @@ gql_single_event <- graphql_query_generator(
)
ret
},
combiner_fn = append,
total_fn = function(x) {
groupByUrlname <- x$data$groupByUrlname
sum(c(
Expand All @@ -220,29 +226,94 @@ gql_single_event <- graphql_query_generator(
groupByUrlname$pastEvents$count
))
},
combiner_fn = append
pb_format = "[:bar] :current/:total :eta"
)

# gql_single_event <- graphql_query_generator(
# "single_event",
# cursor_fn = function(response) {
# # str(response, max.level = 5)
# pageInfo <- response$data$groupByUrlname$pastEvents$pageInfo
# # str(pageInfo)
# if (pageInfo$hasNextPage) {
# list(cursor = pageInfo$endCursor)
# } else {
# NULL
# }
# },
# extract_fn = function(x) {
# x$data$groupByUrlname$pastEvents$edges
# },
# total_fn = function(x) {
# x$data$groupByUrlname$pastEvents$count
# },
# combiner_fn = append
# )
gql_find_groups <- graphql_query_generator(
"find_groups",
cursor_fn = function(x) {
pageInfo <- x$data$keywordSearch$pageInfo
str(pageInfo)
if (pageInfo$hasNextPage) {
list(cursor = pageInfo$endCursor)
} else {
NULL
}
},
combiner_fn = append,
extract_fn = function(x) {
groups <- lapply(x$data$keywordSearch$edges, function(item) {
item$node$result
})
groups <- add_group_locations(groups)
groups
},
total_fn = function(x) {
x$data$keywordSearch$count
Inf
},
pb_format = "- :current/?? :elapsed :spin"
)

# If this function returns empty results, then it is being rate limited
# I don't know how we should approach this.
# A single query can _touch_ 500 points...
# > The API currently allows you to have 500 points in your queries every 60 seconds.
add_group_locations <- function(groups) {

location_txt <- lapply(groups, function(group) {
txt <- "
<< name >>:findLocation(lat: << lat >>, lon: << lon >>) {
city
localized_country_name
name_string
}"
glue::glue_data(
list(
name = paste0("m", rlang::hash(group)),
lat = group$latitude,
lon = group$longitude
),
txt,
.open = "<<", .close = ">>", .trim = FALSE
)
})

query <- paste0(
"query { ",
paste0(location_txt, collapse = "\n"), "\n",
"}"
)
# cat(query, "\n", sep = "")

result <- graphql_query(query)

# Add theh localized country name if the data exists
# Return the the updated groups
Map(
groups,
result$data,
f = function(group, locations) {
for (location in locations) {
if (group$city == location$city) {
group$localized_country_name <- location$localized_country_name
group$name_string <- location$name_string
return(group)
}
}
# No city match at this point
if (length(locations) == 0) {
group$localized_country_name <- NA
group$name_string <- NA
} else {
first_location <- locations[[1]]
group$localized_country_name <- first_location$localized_country_name
group$name_string <- first_location$name_string
}
return(group)
}
)
}



Expand All @@ -256,5 +327,9 @@ if (FALSE) {

x <- gql_single_event(urlname = "Data-Science-DC", extra_graphql = "host { name }")

x <- graphql_file("location", lat = 10.54, lon = -66.93)

x <- gql_find_groups(topicCategoryId = 546, query = "R-Ladies")


}
64 changes: 64 additions & 0 deletions inst/graphql/find_groups.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
query keywordSearch(
# $topicCategoryId: Int! = 546
$topicCategoryId: Int!
$searchSources: [SearchSources!]! = [GROUPS]
# $query: String! = "R-Ladies"
$query: String!
$lat: Float = 0
$lon: Float = 0
$radius: Int = 100000000
$first: Int = 1000
$cursor: String
) {
keywordSearch(
input: { first: $first, after: $cursor }
filter: {
query: $query
lat: $lat
lon: $lon
radius: $radius
topicCategoryId: $topicCategoryId
source: $searchSources
}
) {
pageInfo {
hasNextPage
endCursor
}
count
edges {
# cursor
node {
# id
result {
... on Group {
id
name
urlname
latitude
longitude
city
state
country
membershipMetadata {
status
}
memberships {
count
}
foundedDate
timezone
joinMode
who: customMemberLabel
isPrivate
category: topicCategory {
id
name
}
<< extra_graphql >>
}
}
}
}
}
}
10 changes: 10 additions & 0 deletions inst/graphql/location.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Currently not used directly, but useful for debugging
query location($lat: Float = 0, $lon: Float = 0) {
findLocation(lat: $lat, lon: $lon) {
lat
lon
city
localized_country_name
name_string
}
}
Loading