Problem: Mongo query for get_spent too complicated

Solution: Simplify query using $elemMatch
This commit is contained in:
Vanshdeep Singh 2018-09-24 12:22:15 +02:00
parent fc1920cb7a
commit 9929d8a28a
4 changed files with 23 additions and 27 deletions

View File

@ -91,11 +91,10 @@ def get_assets(conn, asset_ids):
@register_query(LocalMongoDBConnection) @register_query(LocalMongoDBConnection)
def get_spent(conn, transaction_id, output): def get_spent(conn, transaction_id, output):
query_array = [{'transaction_id': transaction_id, query = {'inputs':
'output_index': output}, {'$elemMatch':
{'output_index': output, {'$and': [{'fulfills.transaction_id': transaction_id},
'transaction_id': transaction_id}] {'fulfills.output_index': output}]}}}
query = {'inputs.fulfills': {'$in': query_array}}
return conn.run( return conn.run(
conn.collection('transactions') conn.collection('transactions')
@ -184,15 +183,18 @@ def get_owned_ids(conn, owner):
@register_query(LocalMongoDBConnection) @register_query(LocalMongoDBConnection)
def get_spending_transactions(conn, inputs): def get_spending_transactions(conn, inputs):
transaction_ids = [i['transaction_id'] for i in inputs]
output_indexes = [i['output_index'] for i in inputs]
query = {'inputs':
{'$elemMatch':
{'$and':
[
{'fulfills.transaction_id': {'$in': transaction_ids}},
{'fulfills.output_index': {'$in': output_indexes}}
]}}}
cursor = conn.run( cursor = conn.run(
conn.collection('transactions').aggregate([ conn.collection('transactions').find(query, {'_id': False}))
{'$match': {
'inputs.fulfills': {
'$in': inputs,
},
}},
{'$project': {'_id': False}}
]))
return cursor return cursor

View File

@ -274,12 +274,6 @@ class TransactionLink(object):
'output_index': self.output, 'output_index': self.output,
} }
def to_query(self):
return [{'transaction_id': self.txid,
'output_index': self.output},
{'output_index': self.output,
'transaction_id': self.txid}]
def to_uri(self, path=''): def to_uri(self, path=''):
if self.txid is None and self.output is None: if self.txid is None and self.output is None:
return None return None

View File

@ -5,7 +5,6 @@
from bigchaindb.utils import condition_details_has_owner from bigchaindb.utils import condition_details_has_owner
from bigchaindb.backend import query from bigchaindb.backend import query
from bigchaindb.common.transaction import TransactionLink from bigchaindb.common.transaction import TransactionLink
from itertools import chain
class FastQuery(): class FastQuery():
@ -29,7 +28,7 @@ class FastQuery():
Args: Args:
outputs: list of TransactionLink outputs: list of TransactionLink
""" """
links = list(chain.from_iterable([o.to_query() for o in outputs])) links = [o.to_dict() for o in outputs]
txs = list(query.get_spending_transactions(self.connection, links)) txs = list(query.get_spending_transactions(self.connection, links))
spends = {TransactionLink.from_dict(input_['fulfills']) spends = {TransactionLink.from_dict(input_['fulfills'])
for tx in txs for tx in txs
@ -42,7 +41,7 @@ class FastQuery():
Args: Args:
outputs: list of TransactionLink outputs: list of TransactionLink
""" """
links = list(chain.from_iterable([o.to_query() for o in outputs])) links = [o.to_dict() for o in outputs]
txs = list(query.get_spending_transactions(self.connection, links)) txs = list(query.get_spending_transactions(self.connection, links))
spends = {TransactionLink.from_dict(input_['fulfills']) spends = {TransactionLink.from_dict(input_['fulfills'])
for tx in txs for tx in txs

View File

@ -71,7 +71,7 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
[carol.public_key], [carol.public_key],
[([carol.public_key], 8)], [([carol.public_key], 8)],
).sign([carol.private_key]) ).sign([carol.private_key])
assert b.validate_transaction(tx_1) assert tx_1.validate(b)
b.store_bulk_transactions([tx_1]) b.store_bulk_transactions([tx_1])
tx_2 = Transaction.transfer( tx_2 = Transaction.transfer(
@ -81,7 +81,7 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
([carol.public_key], 4)], ([carol.public_key], 4)],
asset_id=tx_1.id, asset_id=tx_1.id,
).sign([carol.private_key]) ).sign([carol.private_key])
assert b.validate_transaction(tx_2) assert tx_2.validate(b)
b.store_bulk_transactions([tx_2]) b.store_bulk_transactions([tx_2])
tx_3 = Transaction.transfer( tx_3 = Transaction.transfer(
@ -90,7 +90,7 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
([carol.public_key], 3)], ([carol.public_key], 3)],
asset_id=tx_1.id, asset_id=tx_1.id,
).sign([carol.private_key]) ).sign([carol.private_key])
assert b.validate_transaction(tx_3) assert tx_3.validate(b)
b.store_bulk_transactions([tx_3]) b.store_bulk_transactions([tx_3])
tx_4 = Transaction.transfer( tx_4 = Transaction.transfer(
@ -98,7 +98,7 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
[([bob.public_key], 3)], [([bob.public_key], 3)],
asset_id=tx_1.id, asset_id=tx_1.id,
).sign([alice.private_key]) ).sign([alice.private_key])
assert b.validate_transaction(tx_4) assert tx_4.validate(b)
b.store_bulk_transactions([tx_4]) b.store_bulk_transactions([tx_4])
tx_5 = Transaction.transfer( tx_5 = Transaction.transfer(
@ -106,7 +106,8 @@ def test_get_spent_issue_1271(b, alice, bob, carol):
[([alice.public_key], 2)], [([alice.public_key], 2)],
asset_id=tx_1.id, asset_id=tx_1.id,
).sign([bob.private_key]) ).sign([bob.private_key])
assert b.validate_transaction(tx_5) assert tx_5.validate(b)
b.store_bulk_transactions([tx_5]) b.store_bulk_transactions([tx_5])
assert b.get_spent(tx_2.id, 0) == tx_5 assert b.get_spent(tx_2.id, 0) == tx_5