rushdb 1.19.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rushdb-2.2.0/PKG-INFO +265 -0
- rushdb-2.2.0/README.md +240 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/pyproject.toml +18 -38
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/__init__.py +13 -2
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/__init__.py +2 -0
- rushdb-2.2.0/src/rushdb/api/ai.py +248 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/records.py +298 -135
- rushdb-2.2.0/src/rushdb/api/relationship_patterns.py +61 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/relationships.py +19 -43
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/transactions.py +47 -2
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/client.py +43 -12
- rushdb-2.2.0/src/rushdb/common.py +20 -0
- rushdb-2.2.0/src/rushdb/models/api_response.py +34 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/property.py +1 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/record.py +64 -39
- rushdb-2.2.0/src/rushdb/models/result.py +250 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/search_query.py +2 -1
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/transaction.py +2 -2
- {rushdb-1.19.0 → rushdb-2.2.0}/tests/test_create_import.py +2 -2
- rushdb-2.2.0/tests/test_relationship_patterns.py +54 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/tests/test_search_query.py +138 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/tests/test_search_result.py +257 -7
- {rushdb-1.19.0 → rushdb-2.2.0}/uv.lock +1 -1
- rushdb-1.19.0/PKG-INFO +0 -1639
- rushdb-1.19.0/README.md +0 -1614
- rushdb-1.19.0/src/rushdb/common.py +0 -9
- rushdb-1.19.0/src/rushdb/models/result.py +0 -116
- {rushdb-1.19.0 → rushdb-2.2.0}/.env.example +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/.github/workflows/ci.yml +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/.gitignore +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/CODE_OF_CONDUCT.md +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/CONTRIBUTING.md +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/LICENSE +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/rushdb-logo.svg +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/__init__.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/base.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/labels.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/properties.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/api/query.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/__init__.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/models/relationship.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/src/rushdb/utils/token_prefix.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/tests/__init__.py +0 -0
- {rushdb-1.19.0 → rushdb-2.2.0}/tests/test_base_setup.py +0 -0
rushdb-2.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rushdb
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: RushDB Python SDK — memory layer for AI agents and modern apps
|
|
5
|
+
Project-URL: Homepage, https://github.com/rush-db/rushdb-python
|
|
6
|
+
Project-URL: Repository, https://github.com/rush-db/rushdb-python
|
|
7
|
+
Project-URL: Documentation, https://docs.rushdb.com
|
|
8
|
+
Author-email: RushDB Team <hi@rushdb.com>
|
|
9
|
+
License: Apache-2.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent memory,agent-memory,ai agents,ai memory,ai-agents,ai-memory,cloud,database,embedding,embeddings,graph,graph database,graph-database,json normalization,json-normalization,knowledge graph,knowledge-graph,llm memory,llm-memory,mcp,memory layer,memory-layer,no-schema,persistence,rag,relationships,rest api,rest-api,retrieval augmented generation,rush db,rush-db,rushdb,schema-less,schemaless,self-hosted,vector search,vector-search
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
+
Requires-Dist: requests>=2.31.0
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: black>=23.7.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
18
|
+
Requires-Dist: mypy>=1.4.1; extra == 'dev'
|
|
19
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
20
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
21
|
+
Requires-Dist: ruff>=0.0.280; extra == 'dev'
|
|
22
|
+
Requires-Dist: types-python-dateutil>=2.8.19.14; extra == 'dev'
|
|
23
|
+
Requires-Dist: types-requests>=2.31.0.1; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
<div align="center">
|
|
27
|
+
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
# RushDB — Python SDK
|
|
31
|
+
|
|
32
|
+
### The memory layer for AI agents and apps.
|
|
33
|
+
|
|
34
|
+
Push any JSON. Get graph relationships and vector search — automatically.
|
|
35
|
+
No schema. No pipeline. No glue code.
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+

|
|
39
|
+

|
|
40
|
+
|
|
41
|
+
[📖 Documentation](https://docs.rushdb.com/python-sdk/introduction) • [🌐 Website](https://rushdb.com) • [☁️ Cloud](https://app.rushdb.com)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Why RushDB
|
|
48
|
+
|
|
49
|
+
Agents need memory. Apps need connected data. The standard answer involves multiple databases, schema design, and an embedding pipeline before you write a single useful line of business logic.
|
|
50
|
+
|
|
51
|
+
RushDB skips all of that. Push any JSON — nested structure becomes a traversable graph, string properties become semantically searchable, type inference happens automatically.
|
|
52
|
+
|
|
53
|
+
Works with LangChain, CrewAI, AutoGen, or any Python AI framework.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install rushdb
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Agent memory in 3 lines
|
|
66
|
+
|
|
67
|
+
Get an API key at [app.rushdb.com](https://app.rushdb.com).
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from rushdb import RushDB
|
|
71
|
+
|
|
72
|
+
db = RushDB('RUSHDB_API_KEY')
|
|
73
|
+
|
|
74
|
+
# Store an agent action — graph links sessions and context automatically
|
|
75
|
+
db.records.create(
|
|
76
|
+
label='MEMORY',
|
|
77
|
+
data={
|
|
78
|
+
'agent_id': 'agent-42',
|
|
79
|
+
'session_id': 'sess-001',
|
|
80
|
+
'action': 'summarized',
|
|
81
|
+
'topic': 'Q4 results',
|
|
82
|
+
'output': summary_text,
|
|
83
|
+
},
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Recall — traverse relationships, filter by properties
|
|
87
|
+
results = db.records.find({
|
|
88
|
+
'labels': ['MEMORY'],
|
|
89
|
+
'where': {
|
|
90
|
+
'agent_id': 'agent-42',
|
|
91
|
+
'topic': {'$contains': 'Q4'},
|
|
92
|
+
},
|
|
93
|
+
'limit': 10,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
for memory in results:
|
|
97
|
+
print(memory.get('output'))
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Graph traversal
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Push nested JSON — relationships created automatically
|
|
106
|
+
db.records.create_many('COMPANY', {
|
|
107
|
+
'name': 'Acme Corp',
|
|
108
|
+
'DEPARTMENT': [{
|
|
109
|
+
'name': 'Engineering',
|
|
110
|
+
'EMPLOYEE': [{
|
|
111
|
+
'name': 'Alice',
|
|
112
|
+
'role': 'Staff Engineer',
|
|
113
|
+
}]
|
|
114
|
+
}]
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
# Traverse the auto-created graph
|
|
118
|
+
engineers = db.records.find({
|
|
119
|
+
'labels': ['EMPLOYEE'],
|
|
120
|
+
'where': {
|
|
121
|
+
'role': {'$contains': 'Engineer'},
|
|
122
|
+
'DEPARTMENT': {'COMPANY': {'name': 'Acme Corp'}},
|
|
123
|
+
},
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
# Constrain by relationship type and direction
|
|
127
|
+
authored_posts = db.records.find({
|
|
128
|
+
'labels': ['USER'],
|
|
129
|
+
'where': {
|
|
130
|
+
'POST': {
|
|
131
|
+
'$relation': {'type': 'AUTHORED', 'direction': 'out'},
|
|
132
|
+
'title': {'$contains': 'graph'},
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
'limit': 10,
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
# Manage relationships explicitly
|
|
139
|
+
user = db.records.find_uniq({'labels': ['USER'], 'where': {'name': 'Alice'}})
|
|
140
|
+
company = db.records.find_uniq({'labels': ['COMPANY'], 'where': {'name': 'Acme Corp'}})
|
|
141
|
+
user.attach(target=company, options={'type': 'WORKS_AT', 'direction': 'out'})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Importing CSV
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
csv_data = "name,email,age\nJohn,john@example.com,30\nJane,jane@example.com,25"
|
|
150
|
+
|
|
151
|
+
db.records.import_csv(
|
|
152
|
+
label='USER',
|
|
153
|
+
data=csv_data,
|
|
154
|
+
options={'returnResult': True, 'suggestTypes': True},
|
|
155
|
+
parse_config={'header': True, 'skipEmptyLines': True, 'dynamicTyping': True},
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## SearchResult
|
|
162
|
+
|
|
163
|
+
`db.records.find()` returns a `SearchResult` — a list-like container with pagination metadata.
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
result = db.records.find({
|
|
167
|
+
'where': {'status': 'active'},
|
|
168
|
+
'limit': 10,
|
|
169
|
+
'skip': 0,
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
# List-like usage
|
|
173
|
+
print(f"Loaded {len(result)} of {result.total} total")
|
|
174
|
+
print(f"Has more: {result.has_more}")
|
|
175
|
+
|
|
176
|
+
for record in result:
|
|
177
|
+
print(record.get('name'))
|
|
178
|
+
|
|
179
|
+
# Indexing and slicing
|
|
180
|
+
first = result[0]
|
|
181
|
+
top_five = result[:5]
|
|
182
|
+
|
|
183
|
+
# Boolean check
|
|
184
|
+
if result:
|
|
185
|
+
process(result[0])
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Property | Type | Description |
|
|
189
|
+
| -------------- | -------------- | ------------------------------------------- |
|
|
190
|
+
| `data` | `List[Record]` | The result items |
|
|
191
|
+
| `total` | `int` | Total matching records in the database |
|
|
192
|
+
| `has_more` | `bool` | Whether more records exist beyond this page |
|
|
193
|
+
| `search_query` | `dict` | The query that produced this result |
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Record API
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
user = db.records.create('USER', {
|
|
201
|
+
'name': 'Alice',
|
|
202
|
+
'email': 'alice@example.com',
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
# Safe field access
|
|
206
|
+
name = user.get('name') # 'Alice'
|
|
207
|
+
phone = user.get('phone', 'N/A') # 'N/A'
|
|
208
|
+
|
|
209
|
+
# Clean data (excludes internal __id, __label fields)
|
|
210
|
+
data = user.get_data() # {'name': 'Alice', 'email': '...'}
|
|
211
|
+
full = user.get_data(exclude_internal=False) # includes __id, __label, etc.
|
|
212
|
+
|
|
213
|
+
# Existence check (no exception if record was deleted)
|
|
214
|
+
if user.exists:
|
|
215
|
+
user.update({'status': 'active'})
|
|
216
|
+
|
|
217
|
+
# String representations
|
|
218
|
+
repr(user) # Record(id='abc-123', label='USER')
|
|
219
|
+
str(user) # USER: Alice
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Transactions
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
with db.transactions.begin() as tx:
|
|
228
|
+
record_a = db.records.create('NODE', {'value': 1}, transaction=tx)
|
|
229
|
+
record_b = db.records.create('NODE', {'value': 2}, transaction=tx)
|
|
230
|
+
record_a.attach(target=record_b, options={'type': 'LINKED'}, transaction=tx)
|
|
231
|
+
# auto-committed on exit, rolled back on exception
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Configuration
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from rushdb import RushDB
|
|
240
|
+
|
|
241
|
+
db = RushDB(
|
|
242
|
+
'RUSHDB_API_KEY',
|
|
243
|
+
url='http://your-rushdb-server.com/api/v1', # default: https://api.rushdb.com/api/v1
|
|
244
|
+
timeout=30,
|
|
245
|
+
)
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Documentation
|
|
251
|
+
|
|
252
|
+
[docs.rushdb.com/python-sdk](https://docs.rushdb.com/python-sdk/introduction) — full API reference, vector search, aggregations, and more.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Support
|
|
257
|
+
|
|
258
|
+
- [GitHub Issues](https://github.com/rush-db/rushdb-python/issues) — bug reports and feature requests
|
|
259
|
+
- [Email](mailto:support@rushdb.com) — direct support
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Contributing
|
|
264
|
+
|
|
265
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Issues and PRs welcome.
|
rushdb-2.2.0/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
# RushDB — Python SDK
|
|
6
|
+
|
|
7
|
+
### The memory layer for AI agents and apps.
|
|
8
|
+
|
|
9
|
+
Push any JSON. Get graph relationships and vector search — automatically.
|
|
10
|
+
No schema. No pipeline. No glue code.
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
[📖 Documentation](https://docs.rushdb.com/python-sdk/introduction) • [🌐 Website](https://rushdb.com) • [☁️ Cloud](https://app.rushdb.com)
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Why RushDB
|
|
23
|
+
|
|
24
|
+
Agents need memory. Apps need connected data. The standard answer involves multiple databases, schema design, and an embedding pipeline before you write a single useful line of business logic.
|
|
25
|
+
|
|
26
|
+
RushDB skips all of that. Push any JSON — nested structure becomes a traversable graph, string properties become semantically searchable, type inference happens automatically.
|
|
27
|
+
|
|
28
|
+
Works with LangChain, CrewAI, AutoGen, or any Python AI framework.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install rushdb
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Agent memory in 3 lines
|
|
41
|
+
|
|
42
|
+
Get an API key at [app.rushdb.com](https://app.rushdb.com).
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from rushdb import RushDB
|
|
46
|
+
|
|
47
|
+
db = RushDB('RUSHDB_API_KEY')
|
|
48
|
+
|
|
49
|
+
# Store an agent action — graph links sessions and context automatically
|
|
50
|
+
db.records.create(
|
|
51
|
+
label='MEMORY',
|
|
52
|
+
data={
|
|
53
|
+
'agent_id': 'agent-42',
|
|
54
|
+
'session_id': 'sess-001',
|
|
55
|
+
'action': 'summarized',
|
|
56
|
+
'topic': 'Q4 results',
|
|
57
|
+
'output': summary_text,
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Recall — traverse relationships, filter by properties
|
|
62
|
+
results = db.records.find({
|
|
63
|
+
'labels': ['MEMORY'],
|
|
64
|
+
'where': {
|
|
65
|
+
'agent_id': 'agent-42',
|
|
66
|
+
'topic': {'$contains': 'Q4'},
|
|
67
|
+
},
|
|
68
|
+
'limit': 10,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
for memory in results:
|
|
72
|
+
print(memory.get('output'))
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Graph traversal
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
# Push nested JSON — relationships created automatically
|
|
81
|
+
db.records.create_many('COMPANY', {
|
|
82
|
+
'name': 'Acme Corp',
|
|
83
|
+
'DEPARTMENT': [{
|
|
84
|
+
'name': 'Engineering',
|
|
85
|
+
'EMPLOYEE': [{
|
|
86
|
+
'name': 'Alice',
|
|
87
|
+
'role': 'Staff Engineer',
|
|
88
|
+
}]
|
|
89
|
+
}]
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
# Traverse the auto-created graph
|
|
93
|
+
engineers = db.records.find({
|
|
94
|
+
'labels': ['EMPLOYEE'],
|
|
95
|
+
'where': {
|
|
96
|
+
'role': {'$contains': 'Engineer'},
|
|
97
|
+
'DEPARTMENT': {'COMPANY': {'name': 'Acme Corp'}},
|
|
98
|
+
},
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
# Constrain by relationship type and direction
|
|
102
|
+
authored_posts = db.records.find({
|
|
103
|
+
'labels': ['USER'],
|
|
104
|
+
'where': {
|
|
105
|
+
'POST': {
|
|
106
|
+
'$relation': {'type': 'AUTHORED', 'direction': 'out'},
|
|
107
|
+
'title': {'$contains': 'graph'},
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
'limit': 10,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
# Manage relationships explicitly
|
|
114
|
+
user = db.records.find_uniq({'labels': ['USER'], 'where': {'name': 'Alice'}})
|
|
115
|
+
company = db.records.find_uniq({'labels': ['COMPANY'], 'where': {'name': 'Acme Corp'}})
|
|
116
|
+
user.attach(target=company, options={'type': 'WORKS_AT', 'direction': 'out'})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Importing CSV
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
csv_data = "name,email,age\nJohn,john@example.com,30\nJane,jane@example.com,25"
|
|
125
|
+
|
|
126
|
+
db.records.import_csv(
|
|
127
|
+
label='USER',
|
|
128
|
+
data=csv_data,
|
|
129
|
+
options={'returnResult': True, 'suggestTypes': True},
|
|
130
|
+
parse_config={'header': True, 'skipEmptyLines': True, 'dynamicTyping': True},
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## SearchResult
|
|
137
|
+
|
|
138
|
+
`db.records.find()` returns a `SearchResult` — a list-like container with pagination metadata.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
result = db.records.find({
|
|
142
|
+
'where': {'status': 'active'},
|
|
143
|
+
'limit': 10,
|
|
144
|
+
'skip': 0,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
# List-like usage
|
|
148
|
+
print(f"Loaded {len(result)} of {result.total} total")
|
|
149
|
+
print(f"Has more: {result.has_more}")
|
|
150
|
+
|
|
151
|
+
for record in result:
|
|
152
|
+
print(record.get('name'))
|
|
153
|
+
|
|
154
|
+
# Indexing and slicing
|
|
155
|
+
first = result[0]
|
|
156
|
+
top_five = result[:5]
|
|
157
|
+
|
|
158
|
+
# Boolean check
|
|
159
|
+
if result:
|
|
160
|
+
process(result[0])
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
| Property | Type | Description |
|
|
164
|
+
| -------------- | -------------- | ------------------------------------------- |
|
|
165
|
+
| `data` | `List[Record]` | The result items |
|
|
166
|
+
| `total` | `int` | Total matching records in the database |
|
|
167
|
+
| `has_more` | `bool` | Whether more records exist beyond this page |
|
|
168
|
+
| `search_query` | `dict` | The query that produced this result |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Record API
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
user = db.records.create('USER', {
|
|
176
|
+
'name': 'Alice',
|
|
177
|
+
'email': 'alice@example.com',
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
# Safe field access
|
|
181
|
+
name = user.get('name') # 'Alice'
|
|
182
|
+
phone = user.get('phone', 'N/A') # 'N/A'
|
|
183
|
+
|
|
184
|
+
# Clean data (excludes internal __id, __label fields)
|
|
185
|
+
data = user.get_data() # {'name': 'Alice', 'email': '...'}
|
|
186
|
+
full = user.get_data(exclude_internal=False) # includes __id, __label, etc.
|
|
187
|
+
|
|
188
|
+
# Existence check (no exception if record was deleted)
|
|
189
|
+
if user.exists:
|
|
190
|
+
user.update({'status': 'active'})
|
|
191
|
+
|
|
192
|
+
# String representations
|
|
193
|
+
repr(user) # Record(id='abc-123', label='USER')
|
|
194
|
+
str(user) # USER: Alice
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Transactions
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
with db.transactions.begin() as tx:
|
|
203
|
+
record_a = db.records.create('NODE', {'value': 1}, transaction=tx)
|
|
204
|
+
record_b = db.records.create('NODE', {'value': 2}, transaction=tx)
|
|
205
|
+
record_a.attach(target=record_b, options={'type': 'LINKED'}, transaction=tx)
|
|
206
|
+
# auto-committed on exit, rolled back on exception
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Configuration
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from rushdb import RushDB
|
|
215
|
+
|
|
216
|
+
db = RushDB(
|
|
217
|
+
'RUSHDB_API_KEY',
|
|
218
|
+
url='http://your-rushdb-server.com/api/v1', # default: https://api.rushdb.com/api/v1
|
|
219
|
+
timeout=30,
|
|
220
|
+
)
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Documentation
|
|
226
|
+
|
|
227
|
+
[docs.rushdb.com/python-sdk](https://docs.rushdb.com/python-sdk/introduction) — full API reference, vector search, aggregations, and more.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Support
|
|
232
|
+
|
|
233
|
+
- [GitHub Issues](https://github.com/rush-db/rushdb-python/issues) — bug reports and feature requests
|
|
234
|
+
- [Email](mailto:support@rushdb.com) — direct support
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Contributing
|
|
239
|
+
|
|
240
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Issues and PRs welcome.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "rushdb"
|
|
3
|
-
version = "
|
|
4
|
-
description = "RushDB Python SDK"
|
|
3
|
+
version = "2.2.0"
|
|
4
|
+
description = "RushDB Python SDK — memory layer for AI agents and modern apps"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "RushDB Team", email = "hi@rushdb.com"}
|
|
7
7
|
]
|
|
@@ -9,63 +9,43 @@ license = {text = "Apache-2.0"}
|
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
11
11
|
keywords = [
|
|
12
|
+
"rushdb",
|
|
12
13
|
"database",
|
|
13
14
|
"graph database",
|
|
14
15
|
"graph-database",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
16
|
+
"ai memory",
|
|
17
|
+
"ai-memory",
|
|
18
|
+
"agent memory",
|
|
19
|
+
"agent-memory",
|
|
20
|
+
"memory layer",
|
|
21
|
+
"memory-layer",
|
|
22
|
+
"ai agents",
|
|
23
|
+
"ai-agents",
|
|
24
|
+
"llm memory",
|
|
25
|
+
"llm-memory",
|
|
26
|
+
"mcp",
|
|
20
27
|
"vector search",
|
|
21
28
|
"vector-search",
|
|
22
|
-
"similarity search",
|
|
23
|
-
"ai",
|
|
24
|
-
"ai database",
|
|
25
|
-
"artificial intelligence",
|
|
26
|
-
"machine learning",
|
|
27
|
-
"machine-learning",
|
|
28
|
-
"data science",
|
|
29
|
-
"data-science",
|
|
30
29
|
"rag",
|
|
31
30
|
"retrieval augmented generation",
|
|
32
31
|
"embedding",
|
|
33
32
|
"embeddings",
|
|
33
|
+
"knowledge graph",
|
|
34
|
+
"knowledge-graph",
|
|
34
35
|
"json normalization",
|
|
35
36
|
"json-normalization",
|
|
36
37
|
"schema-less",
|
|
37
38
|
"schemaless",
|
|
38
39
|
"no-schema",
|
|
39
|
-
"modern apps",
|
|
40
|
-
"modern-apps",
|
|
41
|
-
"web development",
|
|
42
|
-
"web-development",
|
|
43
|
-
"app backend",
|
|
44
|
-
"app-backend",
|
|
45
|
-
"etl",
|
|
46
|
-
"data pipeline",
|
|
47
|
-
"data-pipeline",
|
|
48
|
-
"data engineering",
|
|
49
|
-
"data-engineering",
|
|
50
|
-
"data analysis",
|
|
51
|
-
"data-analysis",
|
|
52
|
-
"data management",
|
|
53
|
-
"data-management",
|
|
54
|
-
"persistence",
|
|
55
|
-
"fractal api",
|
|
56
|
-
"fractal-api",
|
|
57
40
|
"self-hosted",
|
|
58
41
|
"cloud",
|
|
59
42
|
"rest api",
|
|
60
43
|
"rest-api",
|
|
61
44
|
"graph",
|
|
62
|
-
"graphs",
|
|
63
45
|
"relationships",
|
|
64
|
-
"
|
|
65
|
-
"db",
|
|
46
|
+
"persistence",
|
|
66
47
|
"rush-db",
|
|
67
|
-
"rush db"
|
|
68
|
-
"rushdb"
|
|
48
|
+
"rush db"
|
|
69
49
|
]
|
|
70
50
|
dependencies = [
|
|
71
51
|
"python-dotenv>=1.0.0",
|
|
@@ -3,12 +3,16 @@
|
|
|
3
3
|
Exposes the RushDB class.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from .api.ai import AIAPI
|
|
6
7
|
from .api.query import QueryAPI
|
|
8
|
+
from .api.records import pick_record_id
|
|
9
|
+
from .api.relationship_patterns import RelationshipPatternsAPI
|
|
7
10
|
from .api.relationships import RelationsAPI
|
|
8
11
|
from .client import RushDB
|
|
9
|
-
from .common import RushDBError
|
|
12
|
+
from .common import NonUniqueResultError, RushDBError
|
|
13
|
+
from .models.api_response import ApiResponse
|
|
10
14
|
from .models.property import Property
|
|
11
|
-
from .models.record import Record
|
|
15
|
+
from .models.record import Record, RecordTarget, RelationTarget
|
|
12
16
|
from .models.relationship import RelationshipDetachOptions, RelationshipOptions
|
|
13
17
|
from .models.result import RecordSearchResult, SearchResult
|
|
14
18
|
from .models.transaction import Transaction
|
|
@@ -16,7 +20,11 @@ from .models.transaction import Transaction
|
|
|
16
20
|
__all__ = [
|
|
17
21
|
"RushDB",
|
|
18
22
|
"RushDBError",
|
|
23
|
+
"NonUniqueResultError",
|
|
19
24
|
"Record",
|
|
25
|
+
"RecordTarget",
|
|
26
|
+
"RelationTarget",
|
|
27
|
+
"pick_record_id",
|
|
20
28
|
"RecordSearchResult",
|
|
21
29
|
"SearchResult",
|
|
22
30
|
"Transaction",
|
|
@@ -25,4 +33,7 @@ __all__ = [
|
|
|
25
33
|
"RelationshipDetachOptions",
|
|
26
34
|
"QueryAPI",
|
|
27
35
|
"RelationsAPI",
|
|
36
|
+
"RelationshipPatternsAPI",
|
|
37
|
+
"ApiResponse",
|
|
38
|
+
"AIAPI",
|
|
28
39
|
]
|
|
@@ -2,6 +2,7 @@ from .labels import LabelsAPI
|
|
|
2
2
|
from .properties import PropertiesAPI
|
|
3
3
|
from .query import QueryAPI
|
|
4
4
|
from .records import RecordsAPI
|
|
5
|
+
from .relationship_patterns import RelationshipPatternsAPI
|
|
5
6
|
from .relationships import RelationsAPI
|
|
6
7
|
from .transactions import TransactionsAPI
|
|
7
8
|
|
|
@@ -12,4 +13,5 @@ __all__ = [
|
|
|
12
13
|
"TransactionsAPI",
|
|
13
14
|
"QueryAPI",
|
|
14
15
|
"RelationsAPI",
|
|
16
|
+
"RelationshipPatternsAPI",
|
|
15
17
|
]
|