Skill Tracer
Skills › Scientific Agent Skills › pyzotero › saved-searches.md

saved-searches.md

95 lines · skills/pyzotero/references/saved-searches.md at 5f2bc03

Open on GitHub
1# Saved Searches
2

Saved Searches

Raw lines 1 to 2
3## Retrieving Saved Searches
4
5```python
6# Get all saved search metadata (not results)
7searches = zot.everything(zot.searches())
8# Returns list of dicts with name, key, conditions, version
9
10for search in searches:
11 print(search['data']['name'], search['data']['key'])
12```
14`searches()` returns metadata. The Web API does not execute saved searches. The current **local** API supports `/api/users/0/searches/{searchKey}/items` (or the group equivalent), but Pyzotero 1.15.2 has no dedicated wrapper for that route.

Retrieving Saved Searches

# Get all saved search metadata (not results)
searches = zot.everything(zot.searches())
# Returns list of dicts with name, key, conditions, version

for search in searches:
    print(search['data']['name'], search['data']['key'])

searches() returns metadata. The Web API does not execute saved searches. The current local API supports /api/users/0/searches/{searchKey}/items (or the group equivalent), but Pyzotero 1.15.2 has no dedicated wrapper for that route.

Raw lines 3 to 15
16## Creating Saved Searches
18Each condition dict must have `condition`, `operator`, and `value`:
20```python
21conditions = [
22 {
23 'condition': 'title',
24 'operator': 'contains',
25 'value': 'machine learning'
26 }
28zot.saved_search('ML Papers', conditions)
29```

Creating Saved Searches

Each condition dict must have condition, operator, and value:

conditions = [
    {
        'condition': 'title',
        'operator': 'contains',
        'value': 'machine learning'
    }
]
zot.saved_search('ML Papers', conditions)
Raw lines 16 to 30
31### Multiple Conditions (AND logic)
33```python
34conditions = [
35 {'condition': 'itemType', 'operator': 'is', 'value': 'journalArticle'},
36 {'condition': 'tag', 'operator': 'is', 'value': 'unread'},
37 {'condition': 'date', 'operator': 'isInTheLast', 'value': '3 years'},
39zot.saved_search('Recent Unread Articles', conditions)
40```

Multiple Conditions (AND logic)

conditions = [
    {'condition': 'itemType', 'operator': 'is', 'value': 'journalArticle'},
    {'condition': 'tag', 'operator': 'is', 'value': 'unread'},
    {'condition': 'date', 'operator': 'isInTheLast', 'value': '3 years'},
]
zot.saved_search('Recent Unread Articles', conditions)
Raw lines 31 to 41
42## Deleting Saved Searches
44```python
45# Get search keys first
46searches = zot.everything(zot.searches())
47keys = [s['data']['key'] for s in searches if s['data']['name'] == 'Old Search']
48# The SDK's delete_saved_search() omits the required library-version
49# precondition in 1.15.2. For REMOTE libraries, issue the documented request:
50if keys:
51 if len(keys) > 50:
52 raise ValueError('Review and delete at most 50 search keys per request')
53 version = zot.last_modified_version()
54 response = zot.client.delete(
55 f'https://api.zotero.org/{zot.library_type}/{zot.library_id}/searches',
56 params={'searchKey': ','.join(keys)},
57 headers={**zot.default_headers(), 'If-Unmodified-Since-Version': str(version)},
58 )
59 response.raise_for_status()
60 assert response.status_code == 204
61```

Deleting Saved Searches

# Get search keys first
searches = zot.everything(zot.searches())
keys = [s['data']['key'] for s in searches if s['data']['name'] == 'Old Search']
# The SDK's delete_saved_search() omits the required library-version
# precondition in 1.15.2. For REMOTE libraries, issue the documented request:
if keys:
    if len(keys) > 50:
        raise ValueError('Review and delete at most 50 search keys per request')
    version = zot.last_modified_version()
    response = zot.client.delete(
        f'https://api.zotero.org/{zot.library_type}/{zot.library_id}/searches',
        params={'searchKey': ','.join(keys)},
        headers={**zot.default_headers(), 'If-Unmodified-Since-Version': str(version)},
    )
    response.raise_for_status()
    assert response.status_code == 204
Raw lines 42 to 62
63## Discovering Valid Operators and Conditions
65```python
66# All available operators
67operators = zot.show_operators()
69# All available conditions
70conditions = zot.show_conditions()
72# Operators valid for a specific condition
73title_operators = zot.show_condition_operators('title')
74# A set of supported operator strings in this SDK release.
75```

Discovering Valid Operators and Conditions

# All available operators
operators = zot.show_operators()

# All available conditions
conditions = zot.show_conditions()

# Operators valid for a specific condition
title_operators = zot.show_condition_operators('title')
# A set of supported operator strings in this SDK release.
Raw lines 63 to 76
77## Common Condition/Operator Combinations
79| Condition | Common Operators |
80|-----------|-----------------|
81| `title` | `contains`, `doesNotContain`, `is`, `isNot` |
82| `tag` | `is`, `isNot` |
83| `itemType` | `is`, `isNot` |
84| `date` | `isBefore`, `isInTheLast`, `is`, `isNot` |
85| `creator` | `contains`, `is` |
86| `publicationTitle` | `contains`, `is` |
87| `year` | `is`, `isNot`, `contains` |
88| `collection` | `is`, `isNot` |
89| `fulltextContent` | `contains` |
91`show_operators()` is a mapping; `show_conditions()` is a keys view; `show_condition_operators()` returns a set. These use the SDK's bundled condition definitions, not live server discovery. Check `saved_search()`'s creation result for `failed`, as with `create_items()`. The direct remote delete above is illustrative and does not inherit Pyzotero's backoff wrapper; handle 429/503 and their `Retry-After` headers before another request. Never send it to the local API without local authorization and server-ID handling.
93Sources: [search writes](https://www.zotero.org/support/dev/web_api/v3/write_requests#search_requests), [local search execution](https://www.zotero.org/support/dev/web_api/v3/local_api).
95The SDK 1.15.2 condition table rejects `date/isAfter` despite listing `isAfter` in its global operators. Use a permitted condition/operator pair or an explicitly constructed direct API request after checking the server contract.

Common Condition/Operator Combinations

ConditionCommon Operators
titlecontains, doesNotContain, is, isNot
tagis, isNot
itemTypeis, isNot
dateisBefore, isInTheLast, is, isNot
creatorcontains, is
publicationTitlecontains, is
yearis, isNot, contains
collectionis, isNot
fulltextContentcontains

show_operators() is a mapping; show_conditions() is a keys view; show_condition_operators() returns a set. These use the SDK's bundled condition definitions, not live server discovery. Check saved_search()'s creation result for failed, as with create_items(). The direct remote delete above is illustrative and does not inherit Pyzotero's backoff wrapper; handle 429/503 and their Retry-After headers before another request. Never send it to the local API without local authorization and server-ID handling.

Sources: search writes, local search execution.

The SDK 1.15.2 condition table rejects date/isAfter despite listing isAfter in its global operators. Use a permitted condition/operator pair or an explicitly constructed direct API request after checking the server contract.

Raw lines 77 to 95