Skip to content

Commit b724c6f

Browse files
joowaniJoohwan Oh
authored and
Joohwan Oh
committed
Add Database.get_document method to allow direct retrieval of documents by ID
1 parent 572ac27 commit b724c6f

File tree

4 files changed

+89
-2
lines changed

4 files changed

+89
-2
lines changed

arango/cursor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ def __exit__(self, *_):
3838
self.close(ignore_missing=True)
3939

4040
def __repr__(self):
41+
if self.id is None:
42+
return '<ArangoDB cursor>'
4143
return '<ArangoDB cursor {}>'.format(self.id)
4244

4345
@property

arango/database.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,40 @@ def properties(self):
156156
result['system'] = result.pop('isSystem')
157157
return result
158158

159+
def get_document(self, id, rev=None, match_rev=True):
160+
"""Retrieve a document by its ID (collection/key)
161+
162+
:param id: the document ID
163+
:type id: str | unicode
164+
:returns: the document or ``None`` if the document is missing
165+
:rtype: dict
166+
:param rev: the revision to compare with that of the retrieved document
167+
:type rev: str | unicode
168+
:param match_rev: if ``True``, check if the given revision and
169+
the target document's revisions are the same, otherwise check if
170+
the revisions are different (this flag has an effect only when
171+
**rev** is given)
172+
:type match_rev: bool
173+
:raises arango.exceptions.DocumentRevisionError: if the given revision
174+
does not match the revision of the retrieved document
175+
:raises arango.exceptions.DocumentGetError: if the document cannot
176+
be retrieved from the collection
177+
"""
178+
res = self._conn.get(
179+
'/_api/document/{}'.format(id),
180+
headers=(
181+
{'If-Match' if match_rev else 'If-None-Match': rev}
182+
if rev is not None else {}
183+
)
184+
)
185+
if res.status_code in {304, 412}:
186+
raise DocumentRevisionError(res)
187+
elif res.status_code == 404 and res.error_code == 1202:
188+
return None
189+
elif res.status_code in HTTP_OK:
190+
return res.body
191+
raise DocumentGetError(res)
192+
159193
#########################
160194
# Collection Management #
161195
#########################

tests/test_cursor.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,19 @@ def test_cursor_context_manager():
294294
assert clean_keys(cursor.__next__()) == doc1
295295
with pytest.raises(CursorCloseError):
296296
cursor.close(ignore_missing=False)
297-
assert cursor.close(ignore_missing=True) is False
297+
assert cursor.close(ignore_missing=True) is False
298+
299+
300+
@pytest.mark.order12
301+
def test_cursor_repr_no_id():
302+
col.truncate()
303+
col.import_bulk([doc1, doc2, doc3, doc4])
304+
cursor = db.aql.execute(
305+
'FOR d IN {} RETURN d'.format(col_name),
306+
count=True,
307+
batch_size=2,
308+
ttl=1000,
309+
optimizer_rules=['+all']
310+
)
311+
getattr(cursor, '_data')['id'] = None
312+
assert repr(cursor) == '<ArangoDB cursor>'

tests/test_document.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,8 @@ def test_get():
10331033
with pytest.raises(ArangoError):
10341034
col.get('5', rev='bad_rev')
10351035

1036-
# Test get with correct revision and match_rev turned off
1036+
# TODO uncomment once match_rev flag is fixed
1037+
# # Test get with correct revision and match_rev turned off
10371038
# bad_rev = col['5']['_rev'] + '000'
10381039
# result = col.get('5', rev=bad_rev, match_rev=False)
10391040
# assert result['_key'] == '5'
@@ -1051,6 +1052,41 @@ def test_get():
10511052
iter(bad_col)
10521053

10531054

1055+
def test_get_from_db():
1056+
# Set up test documents
1057+
col.import_bulk(test_docs)
1058+
1059+
# Test get existing document
1060+
result = db.get_document(col_name + '/1')
1061+
assert result['_key'] == '1'
1062+
assert result['val'] == 100
1063+
1064+
# Test get another existing document
1065+
result = db.get_document(col_name + '/2')
1066+
assert result['_key'] == '2'
1067+
assert result['val'] == 100
1068+
1069+
# Test get missing document
1070+
assert db.get_document(col_name + '/6') is None
1071+
1072+
# Test get with correct revision
1073+
good_rev = db.get_document(col_name + '/5')['_rev']
1074+
result = db.get_document(col_name + '/5', rev=good_rev)
1075+
assert result['_key'] == '5'
1076+
assert result['val'] == 300
1077+
1078+
# Test get with invalid revision
1079+
bad_rev = db.get_document(col_name + '/5')['_rev'] + '000'
1080+
with pytest.raises(ArangoError):
1081+
db.get_document(col_name + '/5', rev=bad_rev, match_rev=True)
1082+
with pytest.raises(ArangoError):
1083+
db.get_document(col_name + '/5', rev="bad_rev")
1084+
1085+
# Test get with missing collection
1086+
with pytest.raises(DocumentGetError):
1087+
_ = db.get_document(bad_col_name + '/1')
1088+
1089+
10541090
def test_get_many():
10551091
# Test precondition
10561092
assert len(col) == 0

0 commit comments

Comments
 (0)