--- title: "Designing precise queries across disciplines" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Designing precise queries across disciplines} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = FALSE, comment = "") # Console colour carries no meaning on a rendered page. pkgdown turns it on for # its own build, and the escape sequences then reach the reader as literal text, # so colour is switched off here for a plain vignette render and a site build # alike. The fixed width keeps tibbles inside the documentation column. options(cli.num_colors = 1, cli.hyperlink = FALSE, crayon.enabled = FALSE, width = 80) # Print data frames and tibbles as formatted tables. local({ kp <- function(x, ...) { if (any(vapply(x, is.list, logical(1)))) return(knitr::normal_print(x)) knitr::knit_print(knitr::kable(x)) } for (cls in c("data.frame", "tbl_df", "tbl")) { registerS3method("knit_print", cls, kp, envir = asNamespace("knitr")) } }) ``` ```{r setup} library(scopusflow) ``` A retrieval is only as good as its query. This article shows how to compose correct, field-tagged 'Scopus' queries with `scopus_query()`, which spares you pasting fragments together by hand, where a missing bracket or a mistyped tag quietly returns the wrong records. Everything here is string construction, so it all runs offline, and each query is shown as the literal string it produces. ## Field tags decide where to look A field tag restricts a query to part of a record. `scopus_field_tags()` lists the common ones. ```{r} scopus_field_tags() ``` The most generally useful tag is `TITLE-ABS-KEY`, which searches the title, abstract and keywords together, broad enough to catch a topic without the noise of a full-text match. ## One term, many disciplines The same builder serves any field. Each call below returns the exact query string that would be sent to 'Scopus'. ```{r} # molecular biology scopus_query("CRISPR", .field = "TITLE-ABS-KEY") scopus_query("gravitational waves", .field = "TITLE-ABS-KEY") # physics # environmental science scopus_query("microplastics", .field = "TITLE-ABS-KEY") scopus_query("blockchain", .field = "TITLE-ABS-KEY") # computer science scopus_query("digital humanities", .field = "AUTHKEY") # humanities ``` The last example uses `AUTHKEY`, the author-supplied keywords, which isolates work that self-identifies with a field and so cuts incidental mentions. ## Combining terms with boolean operators Passing several terms joins them. The default operator is `AND`, and `OR` or `AND NOT` are available through `.op`. ```{r} # Two concepts that must co-occur (materials science). scopus_query("perovskite", "solar cell", .field = "TITLE-ABS-KEY") # Spelling variants, either of which will do (economics). scopus_query("behavioral economics", "behavioural economics", .op = "OR") # A family of related tools (molecular biology). scopus_query("CRISPR", "Cas9", "Cas12", .op = "OR") # Excluding a dominant homonym, so the snake stays out of the results. scopus_query("python", "snake", .op = "AND NOT", .field = "TITLE-ABS-KEY") ``` ## From a query to a plan A composed query drops straight into the rest of the workflow. Here it anchors a year-partitioned plan, which keeps each cell under the API's 5000-record ceiling. ```{r} q <- scopus_query("gut microbiome", "immunology", .field = "TITLE-ABS-KEY") q plan <- scopus_plan(q, years = 2015:2022, partition = "year") plan ``` The plan is ready to size and run, which contacts the API. ```{r eval = FALSE} scopus_count(q, years = 2015:2022) records <- scopus_fetch_plan(plan) ``` Without a key, `vignette("scopusflow")` carries the same two steps through to a record set, standing the bundled corpus of real articles in for the harvest, since 'Scopus' records may not be redistributed. ## Searching by affiliation Field tags reach beyond topics. `AFFILORG` searches the affiliation, which turns a query into an institution-level view of output. ```{r} scopus_query("Max Planck", .field = "AFFILORG") ``` ## When a term is empty The builder validates its input, so a stray empty term is caught at construction, well before it can produce a malformed query. ```{r} tryCatch( scopus_query("graphene", ""), scopus_error_bad_input = function(e) conditionMessage(e) ) ```