Merge pull request #1131 from bigchaindb/fix-asset_id-index

Fix asset id index
This commit is contained in:
libscott 2017-02-03 11:08:01 +01:00 committed by GitHub
commit 47d6b8038b
3 changed files with 46 additions and 34 deletions

View File

@ -1,7 +1,6 @@
"""Query implementation for MongoDB""" """Query implementation for MongoDB"""
from time import time from time import time
from itertools import chain
from pymongo import ReturnDocument from pymongo import ReturnDocument
from pymongo import errors from pymongo import errors
@ -86,39 +85,30 @@ def get_blocks_status_from_transaction(conn, transaction_id):
@register_query(MongoDBConnection) @register_query(MongoDBConnection)
def get_txids_filtered(conn, asset_id, operation=None): def get_txids_filtered(conn, asset_id, operation=None):
parts = [] match_create = {
'block.transactions.operation': 'CREATE',
'block.transactions.id': asset_id
}
match_transfer = {
'block.transactions.operation': 'TRANSFER',
'block.transactions.asset.id': asset_id
}
if operation in (Transaction.CREATE, None): if operation == Transaction.CREATE:
# get the txid of the create transaction for asset_id match = match_create
cursor = conn.db['bigchain'].aggregate([ elif operation == Transaction.TRANSFER:
{'$match': { match = match_transfer
'block.transactions.id': asset_id, else:
'block.transactions.operation': 'CREATE' match = {'$or': [match_create, match_transfer]}
}},
{'$unwind': '$block.transactions'},
{'$match': {
'block.transactions.id': asset_id,
'block.transactions.operation': 'CREATE'
}},
{'$project': {'block.transactions.id': True}}
])
parts.append(elem['block']['transactions']['id'] for elem in cursor)
if operation in (Transaction.TRANSFER, None): pipeline = [
# get txids of transfer transaction with asset_id {'$match': match},
cursor = conn.db['bigchain'].aggregate([ {'$unwind': '$block.transactions'},
{'$match': { {'$match': match},
'block.transactions.asset.id': asset_id {'$project': {'block.transactions.id': True}}
}}, ]
{'$unwind': '$block.transactions'}, cursor = conn.db['bigchain'].aggregate(pipeline)
{'$match': { return (elem['block']['transactions']['id'] for elem in cursor)
'block.transactions.asset.id': asset_id
}},
{'$project': {'block.transactions.id': True}}
])
parts.append(elem['block']['transactions']['id'] for elem in cursor)
return chain(*parts)
@register_query(MongoDBConnection) @register_query(MongoDBConnection)

View File

@ -60,8 +60,7 @@ def create_bigchain_secondary_index(conn, dbname):
# secondary index for asset uuid, this field is unique # secondary index for asset uuid, this field is unique
conn.conn[dbname]['bigchain']\ conn.conn[dbname]['bigchain']\
.create_index('block.transactions.transaction.asset.id', .create_index('block.transactions.asset.id', name='asset_id')
name='asset_id')
# secondary index on the public keys of outputs # secondary index on the public keys of outputs
conn.conn[dbname]['bigchain']\ conn.conn[dbname]['bigchain']\

View File

@ -0,0 +1,23 @@
import pytest
from unittest.mock import MagicMock
pytestmark = pytest.mark.bdb
def test_asset_id_index():
from bigchaindb.backend.mongodb.query import get_txids_filtered
from bigchaindb.backend import connect
# Passes a mock in place of a connection to get the query params from the
# query function, then gets the explain plan from MongoDB to test that
# it's using certain indexes.
m = MagicMock()
get_txids_filtered(m, '')
pipeline = m.db['bigchain'].aggregate.call_args[0][0]
run = connect().db.command
res = run('aggregate', 'bigchain', pipeline=pipeline, explain=True)
stages = (res['stages'][0]['$cursor']['queryPlanner']['winningPlan']
['inputStage']['inputStages'])
indexes = [s['inputStage']['indexName'] for s in stages]
assert set(indexes) == {'asset_id', 'transaction_id'}