The QueryBuilder provides a fluent interface for building complex search queries for the DataCite API. It supports boolean operators, wildcards, exact matches, and nested queries.
The QueryBuilder accepts either QueryField enum values or string field names, providing type safety and IDE autocomplete while maintaining flexibility.
use VincentAuger\DataCiteSdk\Query\QueryBuilder;
use VincentAuger\DataCiteSdk\Enums\QueryField;
use VincentAuger\DataCiteSdk\Requests\DOIs\ListDOIs;
use VincentAuger\DataCiteSdk\DataCite;
// Initialize client
$client = new DataCite();
// Using QueryField enum (recommended for type safety and autocomplete)
$query = (new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereContains(QueryField::TITLES_TITLE, 'climate');
// Or using string field names (for flexibility)
$query = (new QueryBuilder)
->whereEquals('publicationYear', '2023')
->whereContains('titles.title', 'climate');
$request = (new ListDOIs)->withQuery($query);
$response = $client->send($request);
$results = $response->dto();All methods accept either a QueryField enum or a string for the field parameter.
Exact match on a field.
use VincentAuger\DataCiteSdk\Enums\QueryField;
(new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereEquals(QueryField::TYPES_RESOURCE_TYPE, 'Dataset')Contains search (case-insensitive).
(new QueryBuilder)
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereContains(QueryField::DESCRIPTIONS_DESCRIPTION, 'machine learning')Negation of exact match.
(new QueryBuilder)
->whereNotEquals(QueryField::TYPES_RESOURCE_TYPE, 'Software')Field starts with value.
(new QueryBuilder)
->whereStartsWith(QueryField::TITLES_TITLE, 'Climate')Field ends with value.
(new QueryBuilder)
->whereEndsWith(QueryField::TITLES_TITLE, 'Analysis')Use custom wildcard patterns (* for multiple characters, ? for single character).
(new QueryBuilder)
->whereWildcard(QueryField::CREATORS_FAMILY_NAME, 'Sm?th') // Matches Smith, Smyth
->whereWildcard(QueryField::CREATORS_NAME_IDENTIFIER, '*') // Any identifier existsCheck if a field has any value.
(new QueryBuilder)
->whereExists(QueryField::CREATORS_NAME_IDENTIFIER) // Has name identifier
->whereExists(QueryField::FUNDING_REFERENCES_FUNDER_NAME) // Has fundingCheck if a field is empty.
(new QueryBuilder)
->whereNotExists(QueryField::CREATORS_AFFILIATION_NAME) // No affiliationExact match with quoted value (for precise matching).
(new QueryBuilder)
->whereExact(QueryField::TITLES_TITLE, 'CrowdoMeter Tweets')Group conditions with AND logic.
(new QueryBuilder)
->whereAnd(function (QueryBuilder $builder) {
$builder
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereContains(QueryField::TITLES_TITLE, 'climate');
})Group conditions with OR logic.
(new QueryBuilder)
->whereOr(function (QueryBuilder $builder) {
$builder
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereContains(QueryField::TITLES_TITLE, 'weather');
})Match any of the provided values (OR logic).
(new QueryBuilder)
->whereIn(QueryField::PUBLICATION_YEAR, ['2022', '2023', '2024'])
->whereIn(QueryField::TYPES_RESOURCE_TYPE, ['Dataset', 'Software'])Exclude all provided values.
(new QueryBuilder)
->whereNotIn(QueryField::TYPES_RESOURCE_TYPE, ['Software', 'Text'])use VincentAuger\DataCiteSdk\Enums\QueryField;
$query = (new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereEquals(QueryField::TYPES_RESOURCE_TYPE, 'Dataset');$query = (new QueryBuilder)
->whereAnd(function (QueryBuilder $builder) {
$builder
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereOr(function (QueryBuilder $builder) {
$builder
->whereContains(QueryField::DESCRIPTIONS_DESCRIPTION, 'temperature')
->whereContains(QueryField::DESCRIPTIONS_DESCRIPTION, 'precipitation');
});
});$query = (new QueryBuilder)
->whereStartsWith(QueryField::TITLES_TITLE, 'Climate')
->whereEndsWith(QueryField::TITLES_TITLE, 'Analysis')
->whereContains(QueryField::CREATORS_NAME, 'Smith');// Find all DOIs with ORCID identifiers
$query = (new QueryBuilder)
->whereEquals(QueryField::CREATORS_NAME_IDENTIFIER_SCHEME, 'ORCID')
->whereExists(QueryField::CREATORS_NAME_IDENTIFIER);
// Find DOIs with ROR affiliations
$query = (new QueryBuilder)
->whereEquals(QueryField::CREATORS_AFFILIATION_IDENTIFIER_SCHEME, 'ROR')
->whereExists(QueryField::CREATORS_AFFILIATION_IDENTIFIER);// Find DOIs that cite or reference other works
$query = (new QueryBuilder)
->whereIn(QueryField::RELATED_IDENTIFIERS_RELATION_TYPE, ['Cites', 'References'])
->whereExists(QueryField::RELATED_IDENTIFIERS_RELATED_IDENTIFIER);
// Find datasets with funding information
$query = (new QueryBuilder)
->whereEquals(QueryField::TYPES_RESOURCE_TYPE_GENERAL, 'Dataset')
->whereExists(QueryField::FUNDING_REFERENCES_FUNDER_NAME);The QueryField enum provides type-safe field names with IDE autocomplete support. All DataCite REST API query fields are available.
QueryField::DOI- DOI identifierQueryField::PUBLICATION_YEAR- Publication yearQueryField::LANGUAGE- Language codeQueryField::VERSION- Version string
QueryField::TITLES_TITLE- Title textQueryField::TITLES_TITLE_TYPE- Title type (e.g., AlternativeTitle)QueryField::TITLES_LANG- Title language
QueryField::CREATORS_NAME- Creator nameQueryField::CREATORS_GIVEN_NAME- Given/first nameQueryField::CREATORS_FAMILY_NAME- Family/last nameQueryField::CREATORS_NAME_TYPE- Personal or OrganizationalQueryField::CREATORS_NAME_IDENTIFIER- ORCID, ISNI, etc.QueryField::CREATORS_NAME_IDENTIFIER_SCHEME- Identifier schemeQueryField::CREATORS_AFFILIATION_NAME- Institution/organization nameQueryField::CREATORS_AFFILIATION_IDENTIFIER- ROR, GRID, etc.QueryField::CREATORS_AFFILIATION_IDENTIFIER_SCHEME- Affiliation identifier scheme
QueryField::CONTRIBUTORS_NAME- Contributor nameQueryField::CONTRIBUTORS_CONTRIBUTOR_TYPE- ContactPerson, DataCurator, etc.QueryField::CONTRIBUTORS_GIVEN_NAME- Given/first nameQueryField::CONTRIBUTORS_FAMILY_NAME- Family/last nameQueryField::CONTRIBUTORS_NAME_IDENTIFIER- Identifier valueQueryField::CONTRIBUTORS_AFFILIATION_NAME- Institution/organization
QueryField::PUBLISHER- Publisher name (simple)QueryField::PUBLISHER_NAME- Publisher name (nested)QueryField::PUBLISHER_IDENTIFIER- Publisher identifier (Schema 4.5+)QueryField::PUBLISHER_IDENTIFIER_SCHEME- Publisher identifier scheme
QueryField::TYPES_RESOURCE_TYPE- Specific resource typeQueryField::TYPES_RESOURCE_TYPE_GENERAL- General category (Dataset, Software, etc.)
QueryField::DESCRIPTIONS_DESCRIPTION- Description textQueryField::DESCRIPTIONS_DESCRIPTION_TYPE- Abstract, Methods, TechnicalInfo, etc.QueryField::DESCRIPTIONS_LANG- Description language
QueryField::SUBJECTS_SUBJECT- Subject/keyword textQueryField::SUBJECTS_SUBJECT_SCHEME- Subject scheme nameQueryField::SUBJECTS_CLASSIFICATION_CODE- Classification code
QueryField::RELATED_IDENTIFIERS_RELATED_IDENTIFIER- Related identifier valueQueryField::RELATED_IDENTIFIERS_RELATION_TYPE- Cites, IsSupplementTo, etc.QueryField::RELATED_IDENTIFIERS_RELATED_IDENTIFIER_TYPE- DOI, URL, arXiv, etc.
QueryField::FUNDING_REFERENCES_FUNDER_NAME- Funder organization nameQueryField::FUNDING_REFERENCES_FUNDER_IDENTIFIER- Funder identifier (ROR, Crossref Funder ID)QueryField::FUNDING_REFERENCES_AWARD_NUMBER- Grant/award numberQueryField::FUNDING_REFERENCES_AWARD_TITLE- Grant/award title
QueryField::RIGHTS_LIST_RIGHTS- License/rights statementQueryField::RIGHTS_LIST_RIGHTS_URI- License URLQueryField::RIGHTS_LIST_RIGHTS_IDENTIFIER- License identifier (e.g., CC-BY-4.0)
QueryField::GEO_LOCATIONS_GEO_LOCATION_PLACE- Place name
QueryField::DATES_DATE- Date valueQueryField::DATES_DATE_TYPE- Accepted, Available, Collected, etc.
QueryField::ALTERNATE_IDENTIFIERS_ALTERNATE_IDENTIFIER- Alternate identifier valueQueryField::IDENTIFIERS_IDENTIFIER- Identifier value (legacy)QueryField::IDENTIFIERS_IDENTIFIER_TYPE- Identifier type
QueryField::RELATED_ITEMS_RELATED_ITEM_TYPE- JournalArticle, Book, etc.QueryField::RELATED_ITEMS_RELATION_TYPE- IsPublishedIn, etc.QueryField::RELATED_ITEMS_TITLES_TITLE- Related item titleQueryField::RELATED_ITEMS_CREATORS_NAME- Related item creator
use VincentAuger\DataCiteSdk\Enums\QueryField;
// Type-safe with autocomplete
$query = (new QueryBuilder)
->whereEquals(QueryField::CREATORS_NAME_IDENTIFIER_SCHEME, 'ORCID')
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereExists(QueryField::FUNDING_REFERENCES_FUNDER_NAME);
// Get the field name as a string if needed
echo QueryField::TITLES_TITLE->value; // "titles.title"The QueryBuilder automatically handles these DataCite search operators:
| Method | Operator | Example |
|---|---|---|
whereEquals |
: |
titles.title:climate |
whereContains |
:* |
titles.title:*climate* |
whereNotEquals |
!: |
types.resourceType!:Software |
whereStartsWith |
:* |
titles.title:Climate* |
whereEndsWith |
:* |
titles.title:*Analysis |
use VincentAuger\DataCiteSdk\DataCite;
use VincentAuger\DataCiteSdk\Query\QueryBuilder;
use VincentAuger\DataCiteSdk\Enums\QueryField;
use VincentAuger\DataCiteSdk\Requests\DOIs\ListDOIs;
use VincentAuger\DataCiteSdk\Enums\SortOption;
// Initialize client
$client = new DataCite();
// Complex query with sorting and pagination
$request = (new ListDOIs)
->withQuery(
(new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereEquals(QueryField::TYPES_RESOURCE_TYPE, 'Dataset')
)
->withSortDesc(SortOption::CREATED)
->withPageSize(25)
->withAffiliation();
// Execute the request
$response = $client->send($request);
$dois = $response->dto();
// Access results
foreach ($dois->data as $doi) {
echo "{$doi->id}: {$doi->attributes->titles[0]->title}\n";
}In addition to the QueryBuilder, ListDOIs supports direct filter parameters for common filtering needs:
// Filter by provider
$request = ListDOIs::new()
->withProviderId('cern');
// Filter by client (repository)
$request = ListDOIs::new()
->withClientId('cern.zenodo');
// Filter by consortium
$request = ListDOIs::new()
->withConsortiumId('dcan');// Filter by resource type
$request = ListDOIs::new()
->withResourceTypeId('output-management-plan');
// Filter by DOI prefix
$request = ListDOIs::new()
->withPrefix('10.5061');
// Filter by registration year
$request = ListDOIs::new()
->withRegistered('2023');
// Filter by creation year
$request = ListDOIs::new()
->withCreated('2023');
// Filter by schema version
$request = ListDOIs::new()
->withSchemaVersion('4');// DOIs with person information
$request = ListDOIs::new()
->withHasPerson(true);
// DOIs with affiliation information
$request = ListDOIs::new()
->withHasAffiliation(true);
// DOIs with funding references
$request = ListDOIs::new()
->withHasFundingReference(true);
// DOIs with related identifiers
$request = ListDOIs::new()
->withHasRelatedIdentifier(true);
// DOIs with abstracts
$request = ListDOIs::new()
->withHasAbstract(true);
// DOIs with metadata
$request = ListDOIs::new()
->withHasMetadata(true);use VincentAuger\DataCiteSdk\Enums\QueryField;
$request = (new ListDOIs)
->withQuery(
(new QueryBuilder)
->whereContains(QueryField::TITLES_TITLE, 'climate')
)
->withProviderId('cern')
->withCreated('2023')
->withHasPerson(true)
->withSortDesc(SortOption::CREATED)
->withPageSize(25)
->withAffiliation()
->withPublisher();- Use QueryField enum - Get type safety and IDE autocomplete by using
QueryFieldenum values instead of strings - Use specific fields - Search in specific fields rather than all fields for better performance
- Combine with sorting - Use QueryBuilder with sort options for relevant results
- Boolean grouping - Use
whereAnd()andwhereOr()for complex logic - Wildcards - Use
whereContains()for partial matches when exact matching is too restrictive - Field validation - All QueryField enum values map to valid DataCite API field names
- Flexibility - Both enum and string field names are supported for maximum flexibility
use VincentAuger\DataCiteSdk\Enums\QueryField;
// This QueryBuilder:
(new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->whereAnd(function (QueryBuilder $builder) {
$builder
->whereContains(QueryField::TITLES_TITLE, 'climate')
->whereOr(function (QueryBuilder $builder) {
$builder
->whereContains(QueryField::DESCRIPTIONS_DESCRIPTION, 'temperature')
->whereContains(QueryField::DESCRIPTIONS_DESCRIPTION, 'precipitation');
});
})
// Generates this query string:
"publicationYear:2023 (titles.title:*climate* (descriptions.description:*temperature* OR descriptions.description:*precipitation*))"For advanced use cases, you can add raw query strings:
(new QueryBuilder)
->whereEquals(QueryField::PUBLICATION_YEAR, '2023')
->raw('titles.title:(climate OR weather)')
->build();