Filtering and Search
The ZineCore2 API provides powerful filtering, search, and ordering capabilities for all list endpoints.
Query Parameters
All list endpoints (/api/zines/, /api/agents/, etc.) support query parameters for filtering and search.
Basic Syntax
GET /api/{endpoint}/?{parameter}={value}
Multiple parameters:
GET /api/{endpoint}/?{param1}={value1}&{param2}={value2}
Field Filtering
Filter by exact field values.
Zines
Filter by subject:
curl "http://localhost:8000/api/zines/?subject=feminism"
Filter by genre:
curl "http://localhost:8000/api/zines/?genre=personal-zine"
Filter by creator:
curl "http://localhost:8000/api/zines/?creator=agent_judith_arcana"
Filter by language:
curl "http://localhost:8000/api/zines/?language=en"
Multiple filters:
curl "http://localhost:8000/api/zines/?subject=feminism&genre=personal-zine&language=en"
Agents
Filter by kind:
curl "http://localhost:8000/api/agents/?kind=Person"
Filter by public status:
curl "http://localhost:8000/api/agents/?public=true"
Holdings
Filter by zine:
curl "http://localhost:8000/api/holdings/?zine_id=zine_mutate_3_1st"
Filter by repository:
curl "http://localhost:8000/api/holdings/?repository_id=repo_barnard_zine_library"
Filter by access status:
curl "http://localhost:8000/api/holdings/?access_status=reading-room-only"
Filter by digital availability:
curl "http://localhost:8000/api/holdings/?digital_available=true"
Repositories
Filter by kind:
curl "http://localhost:8000/api/repositories/?repository_kind=academic-library"
Filter by country:
curl "http://localhost:8000/api/repositories/?country=US"
Filter by status:
curl "http://localhost:8000/api/repositories/?status=active"
Full-Text Search
Search across multiple text fields using the search parameter.
Zines Search
Searches across: title, abstract, table_of_contents
# Search for "mutate"
curl "http://localhost:8000/api/zines/?search=mutate"
# Search for "abortion"
curl "http://localhost:8000/api/zines/?search=abortion"
# Multi-word search
curl "http://localhost:8000/api/zines/?search=feminist+killjoy"
URL encoding:
- Spaces: + or %20
- Special characters: URL-encoded
Examples:
# "feminist killjoy"
curl "http://localhost:8000/api/zines/?search=feminist+killjoy"
curl "http://localhost:8000/api/zines/?search=feminist%20killjoy"
Agents Search
Searches across: display_name, legal_name, biography, alternative_names
# Search for "arcana"
curl "http://localhost:8000/api/agents/?search=arcana"
# Search for "feminist writer"
curl "http://localhost:8000/api/agents/?search=feminist+writer"
Repositories Search
Searches across: repository_name, description, alternative_names
# Search for "barnard"
curl "http://localhost:8000/api/repositories/?search=barnard"
# Search for "queer zine"
curl "http://localhost:8000/api/repositories/?search=queer+zine"
Ordering (Sorting)
Sort results by field values using the ordering parameter.
Ascending Order
# Sort zines by title (A-Z)
curl "http://localhost:8000/api/zines/?ordering=title"
# Sort agents by name (A-Z)
curl "http://localhost:8000/api/agents/?ordering=display_name"
# Sort repositories by name (A-Z)
curl "http://localhost:8000/api/repositories/?ordering=repository_name"
Descending Order
Prefix with - for descending order:
# Sort zines by most recent first
curl "http://localhost:8000/api/zines/?ordering=-created_at"
# Sort zines by title (Z-A)
curl "http://localhost:8000/api/zines/?ordering=-title"
# Sort repositories by newest first
curl "http://localhost:8000/api/repositories/?ordering=-created_at"
Common Ordering Fields
Zines:
- title — Title (alphabetical)
- created_at — Creation date
- updated_at — Last modified date
Agents:
- display_name — Name (alphabetical)
- created_at — Creation date
Holdings:
- created_at — Creation date
- call_number — Call number (alphabetical)
Repositories:
- repository_name — Name (alphabetical)
- created_at — Creation date
- established — Year established
Combining Filters
Combine search, filtering, and ordering:
Example 1: Feminist Zines, Recent First
curl "http://localhost:8000/api/zines/?subject=feminism&ordering=-created_at"
Explanation:
- Filter: Only zines with subject "feminism"
- Order: Most recent first
Example 2: Search + Filter
curl "http://localhost:8000/api/zines/?search=abortion&subject=reproductive-rights&genre=personal-zine"
Explanation:
- Search: Contains "abortion" in title or abstract
- Filter: Subject is "reproductive-rights"
- Filter: Genre is "personal-zine"
Example 3: Digital Holdings for a Zine
curl "http://localhost:8000/api/holdings/?zine_id=zine_mutate_3_1st&digital_available=true"
Explanation:
- Filter: Holdings of specific zine
- Filter: Only digital versions
Example 4: Active US Libraries
curl "http://localhost:8000/api/repositories/?country=US&repository_kind=academic-library&status=active&ordering=repository_name"
Explanation:
- Filter: Country is US
- Filter: Kind is academic library
- Filter: Status is active
- Order: Alphabetically by name
Pagination
All list endpoints are paginated (25 items per page by default).
Default Pagination
Response:
{
"count": 142,
"next": "http://localhost:8000/api/zines/?page=2",
"previous": null,
"results": [...]
}
Fields:
- count — Total number of results
- next — URL to next page (null if last page)
- previous — URL to previous page (null if first page)
- results — Array of resources
Navigate Pages
Page 1 (default):
curl "http://localhost:8000/api/zines/"
Page 2:
curl "http://localhost:8000/api/zines/?page=2"
Page 3:
curl "http://localhost:8000/api/zines/?page=3"
Custom Page Size
50 items per page:
curl "http://localhost:8000/api/zines/?page_size=50"
100 items per page (max):
curl "http://localhost:8000/api/zines/?page_size=100"
Combine with filters:
curl "http://localhost:8000/api/zines/?subject=feminism&page_size=50&page=2"
Advanced Filtering Patterns
Array Field Filtering (Contains)
For ArrayField fields (creator, subject, genre, etc.), the filter checks if the array contains the value.
Example:
Zine record:
{
"zine_id": "zine_mutate_3",
"creator": ["agent_judith_arcana", "agent_jane_doe"],
"subject": ["feminism", "reproductive-rights", "personal-narratives"]
}
Queries that match:
# Matches (creator contains "agent_judith_arcana")
curl "http://localhost:8000/api/zines/?creator=agent_judith_arcana"
# Matches (creator contains "agent_jane_doe")
curl "http://localhost:8000/api/zines/?creator=agent_jane_doe"
# Matches (subject contains "feminism")
curl "http://localhost:8000/api/zines/?subject=feminism"
# Matches (subject contains "reproductive-rights")
curl "http://localhost:8000/api/zines/?subject=reproductive-rights"
Queries that don't match:
# Doesn't match (creator doesn't contain "agent_other")
curl "http://localhost:8000/api/zines/?creator=agent_other"
# Doesn't match (subject doesn't contain "punk")
curl "http://localhost:8000/api/zines/?subject=punk"
Multiple Values for Same Field
NOT supported directly. Use separate requests instead:
# Get zines with subject "feminism"
curl "http://localhost:8000/api/zines/?subject=feminism"
# Get zines with subject "punk"
curl "http://localhost:8000/api/zines/?subject=punk"
# Then combine results client-side
Workaround: Use search instead:
curl "http://localhost:8000/api/zines/?search=feminism+punk"
Case Sensitivity
Search: Case-insensitive
# These are equivalent:
curl "http://localhost:8000/api/zines/?search=feminism"
curl "http://localhost:8000/api/zines/?search=Feminism"
curl "http://localhost:8000/api/zines/?search=FEMINISM"
Field filtering: Case-sensitive
# These are NOT equivalent:
curl "http://localhost:8000/api/zines/?subject=feminism" # Works
curl "http://localhost:8000/api/zines/?subject=Feminism" # Doesn't work (case mismatch)
Best practice: Use exact vocabulary codes for filtering.
Response Examples
Filtered Response
Request:
curl "http://localhost:8000/api/zines/?subject=feminism&ordering=-created_at&page_size=2"
Response:
{
"count": 42,
"next": "http://localhost:8000/api/zines/?subject=feminism&ordering=-created_at&page_size=2&page=2",
"previous": null,
"results": [
{
"zine_id": "zine_mutate_3_1st",
"title": "Mutate Zine #3: Abortion Stories",
"subject": [
{
"code": "feminism",
"label": "Feminism",
"uri": "https://zinecore.org/v2/subjects#feminism"
}
],
"created_at": "2024-02-25T10:30:00Z"
},
{
"zine_id": "zine_feminist_killjoy_1",
"title": "Feminist Killjoy #1",
"subject": [
{
"code": "feminism",
"label": "Feminism",
"uri": "https://zinecore.org/v2/subjects#feminism"
}
],
"created_at": "2024-02-24T14:00:00Z"
}
]
}
Empty Results
Request:
curl "http://localhost:8000/api/zines/?subject=nonexistent"
Response:
{
"count": 0,
"next": null,
"previous": null,
"results": []
}
Code Examples
Python
import requests
API_BASE = "http://localhost:8000/api"
# Search zines
params = {
"search": "feminist",
"subject": "feminism",
"ordering": "-created_at",
"page_size": 50
}
response = requests.get(f"{API_BASE}/zines/", params=params)
data = response.json()
print(f"Found {data['count']} zines")
for zine in data['results']:
print(f" - {zine['title']}")
# Paginate through all results
url = f"{API_BASE}/zines/?subject=feminism"
while url:
response = requests.get(url)
data = response.json()
for zine in data['results']:
print(zine['title'])
url = data['next'] # Next page URL (or None if last page)
JavaScript
const API_BASE = "http://localhost:8000/api";
// Search zines
const params = new URLSearchParams({
search: "feminist",
subject: "feminism",
ordering: "-created_at",
page_size: 50
});
const response = await fetch(`${API_BASE}/zines/?${params}`);
const data = await response.json();
console.log(`Found ${data.count} zines`);
data.results.forEach(zine => {
console.log(` - ${zine.title}`);
});
// Paginate through all results
let url = `${API_BASE}/zines/?subject=feminism`;
while (url) {
const response = await fetch(url);
const data = await response.json();
data.results.forEach(zine => {
console.log(zine.title);
});
url = data.next; // Next page URL (or null if last page)
}
cURL
# Search with multiple filters
curl -G "http://localhost:8000/api/zines/" \
--data-urlencode "search=feminist" \
--data-urlencode "subject=feminism" \
--data-urlencode "genre=personal-zine" \
--data-urlencode "ordering=-created_at" \
--data-urlencode "page_size=50"
# Filter holdings by zine
curl "http://localhost:8000/api/holdings/?zine_id=zine_mutate_3_1st"
# Filter repositories by country
curl "http://localhost:8000/api/repositories/?country=US&status=active"
Performance Considerations
Indexed Fields
The following fields are indexed for fast filtering:
Zines:
- zine_id (unique index)
- title (btree index)
- creator (GIN index for array)
- subject (GIN index for array)
- genre (GIN index for array)
- created_at (btree index)
Agents:
- agent_id (unique index)
- display_name (btree index)
- kind (btree index)
- public (btree index)
Holdings:
- holding_id (unique index)
- zine_id (foreign key index)
- repository_id (foreign key index)
- (zine_id, repository_id) (composite index)
Repositories:
- repo_id (unique index)
- repository_name (btree index)
- repository_kind (btree index)
- country (btree index)
Optimization Tips
Fast queries:
- Filter by indexed fields
- Use exact matches for IDs
- Limit page size (smaller = faster)
Slower queries:
- Full-text search (scans text fields)
- Ordering by non-indexed fields
- Very large page sizes
Best practices:
- Use filters when possible (faster than search)
- Order by indexed fields (created_at, not abstract)
- Keep page size reasonable (25-100 items)
Troubleshooting
No Results
Problem: Query returns no results
Possible causes:
- Typo in filter value
- Case mismatch (field filtering is case-sensitive)
- Invalid vocabulary code
- No records match criteria
Solutions:
- Check filter values for typos
- Use exact vocabulary codes (check /api/vocabularies/)
- Try broader search instead of exact filtering
- Remove filters one at a time to identify issue
Too Many Results
Problem: Query returns too many results
Solutions:
- Add more filters
- Use search instead of broad filtering
- Increase specificity
Pagination Not Working
Problem: next and previous URLs not working
Possible causes:
- Invalid page number
- Page size too large (max 100)
Solutions:
- Check page number is valid (>= 1, <= total pages)
- Reduce page size to 100 or less
Next Steps
- Output Formats — Export data in 7 different formats
- Zines API — Complete zines endpoint reference
- Authentication — Token authentication guide