mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Change metadata model, fix tests and update docs
This commit is contained in:
parent
832ecb5e63
commit
4eca26782c
@ -366,10 +366,7 @@ def get_new_blocks_feed(conn, start_block_id):
|
||||
|
||||
@register_query(MongoDBConnection)
|
||||
def text_search(conn, search, *, language='english', case_sensitive=False,
|
||||
diacritic_sensitive=False, text_score=False, limit=0, table=None):
|
||||
if table is None:
|
||||
table = 'assets'
|
||||
|
||||
diacritic_sensitive=False, text_score=False, limit=0, table='assets'):
|
||||
cursor = conn.run(
|
||||
conn.collection(table)
|
||||
.find({'$text': {
|
||||
|
@ -384,8 +384,8 @@ class Bigchain(object):
|
||||
for transaction in transactions:
|
||||
# ignore transactions in invalid blocks
|
||||
# FIXME: Isn't there a faster solution than doing I/O again?
|
||||
_, status = self.get_transaction(transaction['id'],
|
||||
include_status=True)
|
||||
txn, status = self.get_transaction(transaction['id'],
|
||||
include_status=True)
|
||||
if status == self.TX_VALID:
|
||||
num_valid_transactions += 1
|
||||
# `txid` can only have been spent in at most on valid block.
|
||||
@ -395,13 +395,7 @@ class Bigchain(object):
|
||||
' with the chain'.format(txid))
|
||||
# if its not and invalid transaction
|
||||
if status is not None:
|
||||
if 'metadata' not in transaction:
|
||||
metadata = list(self.get_metadata([transaction['id']]))
|
||||
metadata = metadata[0] if metadata else None
|
||||
if metadata:
|
||||
metadata.pop('id', None)
|
||||
transaction.update({'metadata': metadata})
|
||||
|
||||
transaction.update({'metadata': txn.metadata})
|
||||
non_invalid_transactions.append(transaction)
|
||||
|
||||
if non_invalid_transactions:
|
||||
@ -672,7 +666,7 @@ class Bigchain(object):
|
||||
"""
|
||||
return backend.query.write_metadata(self.connection, metadata)
|
||||
|
||||
def text_search(self, search, *, limit=0, table=None):
|
||||
def text_search(self, search, *, limit=0, table='assets'):
|
||||
"""
|
||||
Return an iterator of assets that match the text search
|
||||
|
||||
@ -683,9 +677,6 @@ class Bigchain(object):
|
||||
Returns:
|
||||
iter: An iterator of assets that match the text search.
|
||||
"""
|
||||
if table is None:
|
||||
table = 'assets'
|
||||
|
||||
objects = backend.query.text_search(self.connection, search, limit=limit,
|
||||
table=table)
|
||||
|
||||
|
@ -5,8 +5,7 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature,
|
||||
DoubleSpend, InputDoesNotExist,
|
||||
TransactionNotInValidBlock,
|
||||
AssetIdMismatch, AmountError,
|
||||
SybilError, ValidationError,
|
||||
DuplicateTransaction)
|
||||
SybilError, DuplicateTransaction)
|
||||
from bigchaindb.common.transaction import Transaction
|
||||
from bigchaindb.common.utils import (gen_timestamp, serialize,
|
||||
validate_txn_obj, validate_key)
|
||||
@ -119,7 +118,7 @@ class Transaction(Transaction):
|
||||
if 'metadata' not in tx_dict:
|
||||
metadata = metadata[0] if metadata else None
|
||||
if metadata:
|
||||
metadata.pop('id', None)
|
||||
metadata = metadata.get('metadata')
|
||||
|
||||
tx_dict.update({'metadata': metadata})
|
||||
|
||||
@ -406,11 +405,10 @@ class Block(object):
|
||||
metadatas = []
|
||||
for transaction in block_dict['block']['transactions']:
|
||||
metadata = transaction.pop('metadata')
|
||||
if isinstance(metadata, dict):
|
||||
metadata.update({'id': transaction['id']})
|
||||
metadatas.append(metadata)
|
||||
elif metadata:
|
||||
raise ValidationError('Invalid value for metadata')
|
||||
if metadata:
|
||||
metadata_new = {'id': transaction['id'],
|
||||
'metadata': metadata}
|
||||
metadatas.append(metadata_new)
|
||||
|
||||
return (metadatas, block_dict)
|
||||
|
||||
@ -460,16 +458,11 @@ class Block(object):
|
||||
dict: The dict of the reconstructed block.
|
||||
"""
|
||||
# create a dict with {'<txid>': metadata}
|
||||
metadatal = {m.pop('id'): m for m in metadatal}
|
||||
metadatal = {m.pop('id'): m.pop('metadata') for m in metadatal}
|
||||
# add the metadata to their corresponding transactions
|
||||
for transaction in block_dict['block']['transactions']:
|
||||
if 'metadata' not in transaction:
|
||||
metadata = metadatal.get(transaction['id'])
|
||||
if metadata:
|
||||
metadata.pop('id', None)
|
||||
transaction.update({'metadata': metadata})
|
||||
else:
|
||||
transaction.update({'metadata': None})
|
||||
metadata = metadatal.get(transaction['id'], None)
|
||||
transaction.update({'metadata': metadata})
|
||||
return block_dict
|
||||
|
||||
@staticmethod
|
||||
|
@ -452,6 +452,118 @@ Assets
|
||||
text search.
|
||||
|
||||
|
||||
Transaction Metadata
|
||||
--------------------------------
|
||||
|
||||
.. http:get:: /api/v1/metadata
|
||||
|
||||
Return all the metadata that match a given text search.
|
||||
|
||||
:query string text search: Text search string to query.
|
||||
:query int limit: (Optional) Limit the number of returned metadata objects. Defaults
|
||||
to ``0`` meaning return all matching objects.
|
||||
|
||||
.. note::
|
||||
|
||||
Currently this enpoint is only supported if the server is running
|
||||
MongoDB as the backend.
|
||||
|
||||
.. http:get:: /api/v1/metadata/?search={text_search}
|
||||
|
||||
Return all metadata that match a given text search. The ``id`` of the metadata
|
||||
is the same ``id`` of the transaction where it was defined.
|
||||
|
||||
If no metadata match the text search it returns an empty list.
|
||||
|
||||
If the text string is empty or the server does not support text search,
|
||||
a ``400`` is returned.
|
||||
|
||||
The results are sorted by text score.
|
||||
For more information about the behavior of text search see `MongoDB text
|
||||
search behavior <https://docs.mongodb.com/manual/reference/operator/query/text/#behavior>`_
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/metadata/?search=bigchaindb HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"metadata": {"metakey1": "Hello BigchainDB 1!"},
|
||||
"id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
|
||||
},
|
||||
{
|
||||
"metadata": {"metakey2": "Hello BigchainDB 2!"},
|
||||
"id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
|
||||
},
|
||||
{
|
||||
"metadata": {"metakey3": "Hello BigchainDB 3!"},
|
||||
"id": "fa6bcb6a8fdea3dc2a860fcdc0e0c63c9cf5b25da8b02a4db4fb6a2d36d27791"
|
||||
}
|
||||
]
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: The query was executed successfully.
|
||||
:statuscode 400: The query was not executed successfully. Returned if the
|
||||
text string is empty or the server does not support
|
||||
text search.
|
||||
|
||||
.. http:get:: /api/v1/metadata/?search={text_search}&limit={n_documents}
|
||||
|
||||
Return at most ``n`` metadata objects that match a given text search.
|
||||
|
||||
If no metadata match the text search it returns an empty list.
|
||||
|
||||
If the text string is empty or the server does not support text search,
|
||||
a ``400`` is returned.
|
||||
|
||||
The results are sorted by text score.
|
||||
For more information about the behavior of text search see `MongoDB text
|
||||
search behavior <https://docs.mongodb.com/manual/reference/operator/query/text/#behavior>`_
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/metadata/?search=bigchaindb&limit=2 HTTP/1.1
|
||||
Host: example.com
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"metadata": {"msg": "Hello BigchainDB 1!"},
|
||||
"id": "51ce82a14ca274d43e4992bbce41f6fdeb755f846e48e710a3bbb3b0cf8e4204"
|
||||
},
|
||||
{
|
||||
"metadata": {"msg": "Hello BigchainDB 2!"},
|
||||
"id": "b4e9005fa494d20e503d916fa87b74fe61c079afccd6e084260674159795ee31"
|
||||
},
|
||||
]
|
||||
|
||||
:resheader Content-Type: ``application/json``
|
||||
|
||||
:statuscode 200: The query was executed successfully.
|
||||
:statuscode 400: The query was not executed successfully. Returned if the
|
||||
text string is empty or the server does not support
|
||||
text search.
|
||||
|
||||
|
||||
Advanced Usage
|
||||
--------------------------------
|
||||
|
||||
|
@ -29,6 +29,16 @@ def decouple_assets(b, block):
|
||||
return block_dict
|
||||
|
||||
|
||||
def decouple_metadata(b, block, block_dict):
|
||||
# the block comming from the database does not contain the metadata
|
||||
# so we need to pass the block without the metadata and store the metadata
|
||||
# so that the voting pipeline can reconstruct it
|
||||
metadata, block_dict = block.decouple_metadata(block_dict)
|
||||
if metadata:
|
||||
b.write_metadata(metadata)
|
||||
return block_dict
|
||||
|
||||
|
||||
DUMMY_SHA3 = '0123456789abcdef' * 4
|
||||
|
||||
|
||||
@ -89,6 +99,7 @@ def test_vote_validate_block(b):
|
||||
tx = dummy_tx(b)
|
||||
block = b.create_block([tx])
|
||||
block_dict = decouple_assets(b, block)
|
||||
block_dict = decouple_metadata(b, block, block_dict)
|
||||
|
||||
vote_obj = vote.Vote()
|
||||
validation = vote_obj.validate_block(block_dict)
|
||||
@ -230,6 +241,7 @@ def test_valid_block_voting_multiprocessing(b, genesis_block, monkeypatch):
|
||||
|
||||
block = dummy_block(b)
|
||||
block_dict = decouple_assets(b, block)
|
||||
block_dict = decouple_metadata(b, block, block_dict)
|
||||
|
||||
inpipe.put(block_dict)
|
||||
vote_pipeline.start()
|
||||
@ -268,6 +280,7 @@ def test_valid_block_voting_with_create_transaction(b,
|
||||
monkeypatch.setattr('time.time', lambda: 1111111111)
|
||||
block = b.create_block([tx])
|
||||
block_dict = decouple_assets(b, block)
|
||||
block_dict = decouple_metadata(b, block, block_dict)
|
||||
|
||||
inpipe = Pipe()
|
||||
outpipe = Pipe()
|
||||
|
@ -43,7 +43,7 @@ def test_get_metadata(client, b):
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 1
|
||||
assert res.json[0] == {
|
||||
'key': 'my_meta',
|
||||
'metadata': {'key': 'my_meta'},
|
||||
'id': tx.id
|
||||
}
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user