From 800f04cb7023236cae0a9e841de962d8d71e834c Mon Sep 17 00:00:00 2001 From: Lucas Lavandeira <19612265+lucaslavandeira@users.noreply.github.com> Date: Tue, 12 Jun 2018 15:36:59 -0300 Subject: [PATCH 1/4] Indexo catalog_id --- .../apps/metadata/indexer/doc_types.py | 1 + .../apps/metadata/indexer/metadata_indexer.py | 6 ++++-- .../metadata/management/commands/index_metadata.py | 11 +++-------- series_tiempo_ar_api/apps/metadata/tests/tests.py | 4 ++-- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/series_tiempo_ar_api/apps/metadata/indexer/doc_types.py b/series_tiempo_ar_api/apps/metadata/indexer/doc_types.py index 3334b230..6aaafd97 100644 --- a/series_tiempo_ar_api/apps/metadata/indexer/doc_types.py +++ b/series_tiempo_ar_api/apps/metadata/indexer/doc_types.py @@ -15,6 +15,7 @@ class Field(DocType): dataset_theme = Keyword() units = Keyword() dataset_publisher_name = Keyword() + catalog_id = Keyword() # Guardamos una copia como keyword para poder usar en aggregations dataset_source = Text() diff --git a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py index a6decae6..71d010df 100644 --- a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py +++ b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py @@ -14,8 +14,9 @@ class MetadataIndexer(object): - def __init__(self, data_json): + def __init__(self, data_json, catalog_id): self.data_json = data_json + self.catalog_id = catalog_id self.elastic = ElasticInstance.get() logger.info('Hosts de ES: %s', self.elastic.transport.hosts) @@ -57,7 +58,8 @@ def scrap_datajson(self): dataset_source_keyword=dataset.get('source'), dataset_description=dataset.get('description'), dataset_publisher_name=dataset.get('publisher', {}).get('name'), - dataset_theme=themes.get(dataset.get('theme', [None])[0]) + dataset_theme=themes.get(dataset.get('theme', [None])[0]), + catalog_id=self.catalog_id ) actions.append(doc.to_dict(include_meta=True)) return actions diff --git a/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py b/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py index 996e9849..dc85209d 100644 --- a/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py +++ b/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py @@ -17,14 +17,9 @@ def add_arguments(self, parser): parser.add_argument('datajson_url', nargs='*') def handle(self, *args, **options): - if options['datajson_url']: - urls = options['datajson_url'] - else: - urls = [node.catalog_url for node in Node.objects.filter(indexable=True)] - - for url in urls: + for node in Node.objects.filter(indexable=True): try: - data_json = DataJson(url) - MetadataIndexer(data_json).index() + data_json = DataJson(node.catalog_url) + MetadataIndexer(data_json, node.catalog_id).index() except Exception as e: logger.exception(u'Error en la lectura del catálogo: %s', e) diff --git a/series_tiempo_ar_api/apps/metadata/tests/tests.py b/series_tiempo_ar_api/apps/metadata/tests/tests.py index 8f42d17d..bdde29f2 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/tests.py @@ -90,14 +90,14 @@ def setUp(self): def test_scraping(self): catalog = os.path.join(SAMPLES_DIR, 'single_distribution.json') datajson = DataJson(catalog) - result = MetadataIndexer(datajson).scrap_datajson() + result = MetadataIndexer(datajson, 'test_node').scrap_datajson() self.assertEqual(len(result), len(datajson.get_fields()) - 1) def test_scraping_result(self): catalog = os.path.join(SAMPLES_DIR, 'single_distribution.json') datajson = DataJson(catalog) - result = MetadataIndexer(datajson).scrap_datajson() + result = MetadataIndexer(datajson, 'test_node').scrap_datajson() mapping = Field._doc_type.mapping.properties.properties.to_dict() mapping_fields = mapping.keys() From 25a6fc9cfae0865449f239c201b9f4926c2dde2a Mon Sep 17 00:00:00 2001 From: Lucas Lavandeira <19612265+lucaslavandeira@users.noreply.github.com> Date: Tue, 12 Jun 2018 15:59:03 -0300 Subject: [PATCH 2/4] Agrego endpoint y filtros para catalog_id --- .../apps/metadata/constants.py | 3 +- .../indexer/catalog_metadata_indexer.py | 72 ++++++++++++++++ .../apps/metadata/indexer/metadata_indexer.py | 82 ++++--------------- .../management/commands/index_metadata.py | 11 +-- .../apps/metadata/tests/tests.py | 10 +-- series_tiempo_ar_api/apps/metadata/urls.py | 4 +- series_tiempo_ar_api/apps/metadata/views.py | 6 ++ 7 files changed, 106 insertions(+), 82 deletions(-) create mode 100644 series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py diff --git a/series_tiempo_ar_api/apps/metadata/constants.py b/series_tiempo_ar_api/apps/metadata/constants.py index c0fc185d..1ac1d9d2 100644 --- a/series_tiempo_ar_api/apps/metadata/constants.py +++ b/series_tiempo_ar_api/apps/metadata/constants.py @@ -11,5 +11,6 @@ 'dataset_theme': 'dataset_theme', 'units': 'units', 'dataset_publisher_name': 'dataset_publisher_name', - 'dataset_source': 'dataset_source_keyword' + 'dataset_source': 'dataset_source_keyword', + 'catalog_id': 'catalog_id', } diff --git a/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py b/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py new file mode 100644 index 00000000..143a2ce3 --- /dev/null +++ b/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py @@ -0,0 +1,72 @@ +#! coding: utf-8 +from __future__ import print_function + +import logging +from elasticsearch.helpers import parallel_bulk + +from series_tiempo_ar_api.apps.metadata.indexer.doc_types import Field +from series_tiempo_ar_api.libs.indexing.elastic import ElasticInstance + +from . import strings + +logger = logging.getLogger(__name__) + + +class CatalogMetadataIndexer(object): + + def __init__(self, data_json, catalog_id): + self.data_json = data_json + self.catalog_id = catalog_id + self.elastic = ElasticInstance.get() + logger.info('Hosts de ES: %s', self.elastic.transport.hosts) + + def index(self): + logger.info(u'Inicio de la indexación de metadatos de %s', self.catalog_id) + + actions = self.scrap_datajson() + + self.index_actions(actions) + logger.info(u'Fin de la indexación de metadatos') + + def index_actions(self, actions): + for success, info in parallel_bulk(self.elastic, actions): + if not success: + logger.info(strings.INDEXING_ERROR, info) + + def scrap_datajson(self): + themes = self.get_themes(self.data_json['themeTaxonomy']) + datasets = {} + actions = [] + for field in self.data_json.get_fields(only_time_series=True): + dataset = datasets.setdefault(field['dataset_identifier'], + self.get_dataset(identifier=field['dataset_identifier'])) + + doc = Field( + title=field.get('title'), + description=field.get('description'), + id=field.get('id'), + units=field.get('units'), + dataset_title=dataset.get('title'), + dataset_source=dataset.get('source'), + dataset_source_keyword=dataset.get('source'), + dataset_description=dataset.get('description'), + dataset_publisher_name=dataset.get('publisher', {}).get('name'), + dataset_theme=themes.get(dataset.get('theme', [None])[0]), + catalog_id=self.catalog_id + ) + actions.append(doc.to_dict(include_meta=True)) + return actions + + def get_dataset(self, identifier): + for dataset in self.data_json['dataset']: + if dataset['identifier'] == identifier: + return dataset + raise ValueError(u'Identifier no encontrado: {}'.format(identifier)) + + @staticmethod + def get_themes(theme_taxonomy): + themes = {} + for theme in theme_taxonomy: + themes[theme['id']] = theme['label'] + + return themes diff --git a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py index 71d010df..18a96925 100644 --- a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py +++ b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py @@ -1,79 +1,31 @@ #! coding: utf-8 -from __future__ import print_function - import logging -from elasticsearch.helpers import parallel_bulk +from pydatajson import DataJson +from series_tiempo_ar_api.apps.management.models import Node +from series_tiempo_ar_api.apps.metadata.indexer.catalog_metadata_indexer import \ + CatalogMetadataIndexer from series_tiempo_ar_api.apps.metadata.indexer.doc_types import Field from series_tiempo_ar_api.libs.indexing.elastic import ElasticInstance -from . import strings - logger = logging.getLogger(__name__) -class MetadataIndexer(object): +class MetadataIndexer: - def __init__(self, data_json, catalog_id): - self.data_json = data_json - self.catalog_id = catalog_id + def __init__(self, doc_type=Field): self.elastic = ElasticInstance.get() - logger.info('Hosts de ES: %s', self.elastic.transport.hosts) - - def index(self): - logger.info(u'Inicio de la indexación de metadatos') - self.init_index() - - actions = self.scrap_datajson() - - self.index_actions(actions) - logger.info(u'Fin de la indexación de metadatos') + self.doc_type = doc_type - # noinspection PyProtectedMember def init_index(self): - if self.elastic.indices.exists(Field._doc_type.index): - self.elastic.indices.delete(Field._doc_type.index) - Field.init(using=self.elastic) + if self.elastic.indices.exists(self.doc_type.Meta.index): + self.doc_type.init(using=self.elastic) - def index_actions(self, actions): - for success, info in parallel_bulk(self.elastic, actions): - if not success: - logger.info(strings.INDEXING_ERROR, info) - - def scrap_datajson(self): - themes = self.get_themes(self.data_json['themeTaxonomy']) - datasets = {} - actions = [] - for field in self.data_json.get_fields(only_time_series=True): - dataset = datasets.setdefault(field['dataset_identifier'], - self.get_dataset(identifier=field['dataset_identifier'])) - - doc = Field( - title=field.get('title'), - description=field.get('description'), - id=field.get('id'), - units=field.get('units'), - dataset_title=dataset.get('title'), - dataset_source=dataset.get('source'), - dataset_source_keyword=dataset.get('source'), - dataset_description=dataset.get('description'), - dataset_publisher_name=dataset.get('publisher', {}).get('name'), - dataset_theme=themes.get(dataset.get('theme', [None])[0]), - catalog_id=self.catalog_id - ) - actions.append(doc.to_dict(include_meta=True)) - return actions - - def get_dataset(self, identifier): - for dataset in self.data_json['dataset']: - if dataset['identifier'] == identifier: - return dataset - raise ValueError(u'Identifier no encontrado: {}'.format(identifier)) - - @staticmethod - def get_themes(theme_taxonomy): - themes = {} - for theme in theme_taxonomy: - themes[theme['id']] = theme['label'] - - return themes + def run(self): + self.init_index() + for node in Node.objects.filter(indexable=True): + try: + data_json = DataJson(node.catalog_url) + CatalogMetadataIndexer(data_json, node.catalog_id).index() + except Exception as e: + logger.exception(u'Error en la lectura del catálogo: %s', e) diff --git a/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py b/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py index dc85209d..8d66b01b 100644 --- a/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py +++ b/series_tiempo_ar_api/apps/metadata/management/commands/index_metadata.py @@ -2,12 +2,8 @@ import logging from django.core.management import BaseCommand -from pydatajson import DataJson - -from django_datajsonar.models import Node from series_tiempo_ar_api.apps.metadata.indexer.metadata_indexer import MetadataIndexer - logger = logging.getLogger(__name__) @@ -17,9 +13,4 @@ def add_arguments(self, parser): parser.add_argument('datajson_url', nargs='*') def handle(self, *args, **options): - for node in Node.objects.filter(indexable=True): - try: - data_json = DataJson(node.catalog_url) - MetadataIndexer(data_json, node.catalog_id).index() - except Exception as e: - logger.exception(u'Error en la lectura del catálogo: %s', e) + MetadataIndexer() diff --git a/series_tiempo_ar_api/apps/metadata/tests/tests.py b/series_tiempo_ar_api/apps/metadata/tests/tests.py index bdde29f2..7427f572 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/tests.py @@ -10,7 +10,7 @@ from series_tiempo_ar_api.apps.metadata import constants from series_tiempo_ar_api.apps.metadata.indexer.doc_types import Field -from series_tiempo_ar_api.apps.metadata.indexer.metadata_indexer import MetadataIndexer +from series_tiempo_ar_api.apps.metadata.indexer.metadata_indexer import CatalogMetadataIndexer from series_tiempo_ar_api.apps.metadata.queries.query import FieldSearchQuery from .utils import get_mock_search @@ -84,20 +84,20 @@ class IndexerTests(TestCase): def setUp(self): # No mandar datos a la instancia de ES - MetadataIndexer.init_index = mock.Mock() - MetadataIndexer.index_actions = mock.Mock() + CatalogMetadataIndexer.init_index = mock.Mock() + CatalogMetadataIndexer.index_actions = mock.Mock() def test_scraping(self): catalog = os.path.join(SAMPLES_DIR, 'single_distribution.json') datajson = DataJson(catalog) - result = MetadataIndexer(datajson, 'test_node').scrap_datajson() + result = CatalogMetadataIndexer(datajson, 'test_node').scrap_datajson() self.assertEqual(len(result), len(datajson.get_fields()) - 1) def test_scraping_result(self): catalog = os.path.join(SAMPLES_DIR, 'single_distribution.json') datajson = DataJson(catalog) - result = MetadataIndexer(datajson, 'test_node').scrap_datajson() + result = CatalogMetadataIndexer(datajson, 'test_node').scrap_datajson() mapping = Field._doc_type.mapping.properties.properties.to_dict() mapping_fields = mapping.keys() diff --git a/series_tiempo_ar_api/apps/metadata/urls.py b/series_tiempo_ar_api/apps/metadata/urls.py index 1abc0cab..ae80df53 100644 --- a/series_tiempo_ar_api/apps/metadata/urls.py +++ b/series_tiempo_ar_api/apps/metadata/urls.py @@ -1,7 +1,8 @@ #!coding=utf8 from django.conf.urls import url -from .views import search, dataset_source, field_units, dataset_publisher_name, dataset_theme +from .views import search, dataset_source, field_units, \ + dataset_publisher_name, dataset_theme, catalog_id urlpatterns = [ url('^$', search, name='search'), @@ -9,4 +10,5 @@ url('^field_units/$', field_units, name='field_units'), url('^dataset_publisher_name/$', dataset_publisher_name, name='dataset_publisher_name'), url('^dataset_theme/$', dataset_theme, name='dataset_theme'), + url('^catalog_id/$', catalog_id, name='catalog_id'), ] diff --git a/series_tiempo_ar_api/apps/metadata/views.py b/series_tiempo_ar_api/apps/metadata/views.py index 971d620c..e5154b6a 100644 --- a/series_tiempo_ar_api/apps/metadata/views.py +++ b/series_tiempo_ar_api/apps/metadata/views.py @@ -36,3 +36,9 @@ def dataset_theme(request): response = query_field_terms(field='dataset_theme') return JsonResponse(response) + + +def catalog_id(request): + response = query_field_terms(field='catalog_id') + + return JsonResponse(response) From eb4bb602422fa52f318686d01174e290cc63dcca Mon Sep 17 00:00:00 2001 From: Lucas Lavandeira <19612265+lucaslavandeira@users.noreply.github.com> Date: Wed, 13 Jun 2018 10:29:35 -0300 Subject: [PATCH 3/4] =?UTF-8?q?Refactorizo=20dependencias=20y=20agrego=20c?= =?UTF-8?q?asos=20de=20prueba=20a=20indexaci=C3=B3n=20de=20metadatos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../indexer/catalog_metadata_indexer.py | 5 +- .../apps/metadata/indexer/metadata_indexer.py | 7 +- .../apps/metadata/tests/indexer_tests.py | 47 ++ .../samples/second_single_distribution.json | 765 ++++++++++++++++++ .../apps/metadata/tests/tests.py | 4 +- .../apps/metadata/tests/view_tests.py | 14 + 6 files changed, 837 insertions(+), 5 deletions(-) create mode 100644 series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py create mode 100644 series_tiempo_ar_api/apps/metadata/tests/samples/second_single_distribution.json diff --git a/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py b/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py index 143a2ce3..b52a9edb 100644 --- a/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py +++ b/series_tiempo_ar_api/apps/metadata/indexer/catalog_metadata_indexer.py @@ -14,9 +14,10 @@ class CatalogMetadataIndexer(object): - def __init__(self, data_json, catalog_id): + def __init__(self, data_json, catalog_id, doc_type=Field): self.data_json = data_json self.catalog_id = catalog_id + self.doc_type = doc_type self.elastic = ElasticInstance.get() logger.info('Hosts de ES: %s', self.elastic.transport.hosts) @@ -41,7 +42,7 @@ def scrap_datajson(self): dataset = datasets.setdefault(field['dataset_identifier'], self.get_dataset(identifier=field['dataset_identifier'])) - doc = Field( + doc = self.doc_type( title=field.get('title'), description=field.get('description'), id=field.get('id'), diff --git a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py index 18a96925..aeb63bf1 100644 --- a/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py +++ b/series_tiempo_ar_api/apps/metadata/indexer/metadata_indexer.py @@ -16,9 +16,10 @@ class MetadataIndexer: def __init__(self, doc_type=Field): self.elastic = ElasticInstance.get() self.doc_type = doc_type + self.index = self.doc_type._doc_type.index def init_index(self): - if self.elastic.indices.exists(self.doc_type.Meta.index): + if not self.elastic.indices.exists(self.index): self.doc_type.init(using=self.elastic) def run(self): @@ -26,6 +27,8 @@ def run(self): for node in Node.objects.filter(indexable=True): try: data_json = DataJson(node.catalog_url) - CatalogMetadataIndexer(data_json, node.catalog_id).index() + CatalogMetadataIndexer(data_json, node.catalog_id, self.doc_type).index() except Exception as e: logger.exception(u'Error en la lectura del catálogo: %s', e) + + self.elastic.indices.forcemerge(self.index) diff --git a/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py b/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py new file mode 100644 index 00000000..dd8ecf1a --- /dev/null +++ b/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py @@ -0,0 +1,47 @@ +#! coding: utf-8 +import os + +from django.test import TestCase + +from series_tiempo_ar_api.apps.management.models import Node +from series_tiempo_ar_api.apps.metadata.indexer.doc_types import Field +from series_tiempo_ar_api.apps.metadata.indexer.metadata_indexer import MetadataIndexer +from series_tiempo_ar_api.apps.metadata.tests.tests import SAMPLES_DIR +from series_tiempo_ar_api.libs.indexing.elastic import ElasticInstance + +from faker import Faker + +fake = Faker() + + +class IndexerTests(TestCase): + class FakeField(Field): + class Meta: + index = fake.word() + + def setUp(self): + self.elastic = ElasticInstance.get() + + def test_index_two_nodes(self): + Node(catalog_id='first_catalog', + catalog_url=os.path.join(SAMPLES_DIR, 'single_distribution.json'), + indexable=True).save() + Node(catalog_id='second_catalog', + catalog_url=os.path.join(SAMPLES_DIR, 'second_single_distribution.json'), + indexable=True).save() + + MetadataIndexer(doc_type=self.FakeField).run() + + first_catalog_fields = self.FakeField.search(using=ElasticInstance.get())\ + .filter('term', catalog_id='first_catalog')\ + .execute() + + second_catalog_fields = self.FakeField.search(using=ElasticInstance.get())\ + .filter('term', catalog_id='second_catalog')\ + .execute() + + self.assertTrue(first_catalog_fields) + self.assertTrue(second_catalog_fields) + + def tearDown(self): + self.elastic.indices.delete(self.FakeField._doc_type.index) \ No newline at end of file diff --git a/series_tiempo_ar_api/apps/metadata/tests/samples/second_single_distribution.json b/series_tiempo_ar_api/apps/metadata/tests/samples/second_single_distribution.json new file mode 100644 index 00000000..731d5cba --- /dev/null +++ b/series_tiempo_ar_api/apps/metadata/tests/samples/second_single_distribution.json @@ -0,0 +1,765 @@ +{ + "publisher": { + "mbox": "datoseconomicos@mecon.gov.ar", + "name": "Subsecretaría de Programación Macroeconómica." + }, + "license": "Open Database License (ODbL) v1.0", + "description": "Catálogo de datos abiertos de la Subsecretaría de Programación Macroeconómica.", + "language": [ + "SPA" + ], + "superThemeTaxonomy": "http://datos.gob.ar/superThemeTaxonomy.json", + "issued": "2017-09-28", + "rights": "2017-09-28", + "modified": "2017-09-28", + "dataset": [ + { + "publisher": { + "mbox": "datoseconomicos@mecon.gov.ar", + "name": "Subsecretaría de Programación Macroeconómica." + }, + "landingPage": "http://www.minhacienda.gob.ar/secretarias/politica-economica/programacion-macroeconomica/", + "description": "Precios FOB oficiales en dólares por tonelada", + "superTheme": [ + "ECON" + ], + "title": "Precios FOB oficiales", + "language": [ + "SPA" + ], + "issued": "2017-12-11", + "temporal": "1993-01-04/2017-11-29", + "modified": "2018-01-12T07:00:02.490530-03:00", + "source": "Ministerio de Agroindustria", + "theme": [ + "externo" + ], + "keyword": [ + "Información Económica al Día", + "Sector Externo", + "Precios" + ], + "accrualPeriodicity": "R/P1D", + "spatial": "ARG", + "identifier": "358", + "contactPoint": { + "fn": "Subsecretaría de Programación Macroeconómica." + }, + "accessLevel": "ABIERTO", + "distribution": [ + { + "accessURL": "https://www.minhacienda.gob.ar/secretarias/politica-economica/programacion-macroeconomica/", + "scrapingFileSheet": "38. Precios FOB oficiales", + "description": "Precios FOB oficiales. Valores diarios en dólares por tonelada", + "title": "Precios FOB oficiales. Valores diarios", + "dataset_identifier": "358", + "issued": "2017-12-11", + "format": "CSV", + "modified": "2018-01-12T07:00:02.490530-03:00", + "fileName": "precios-fob-oficiales-valores-diarios.csv", + "downloadURL": "http://infra.datos.gob.ar/catalog/sspm/dataset/358/distribution/358.1/download/precios-fob-oficiales-valores-diarios.csv", + "field": [ + { + "distribution_identifier": "358.1", + "title": "indice_tiempo", + "dataset_identifier": "358", + "scrapingIdentifierCell": "A10", + "specialTypeDetail": "R/P1D", + "units": "Dolares por tonelada", + "specialType": "time_index", + "type": "date", + "id": "358.1_INDICE_TIEMPO__13", + "scrapingDataStartCell": "A11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harina de soja, \"Pellets\", de harina de extracción", + "title": "tortas_expellers_pellets_harina_soja_pellets_harina_extr", + "dataset_identifier": "358", + "scrapingIdentifierCell": "B10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPXTR__56", + "scrapingDataStartCell": "B11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harina de soja, \"Pellets\", Harinas de tortas", + "title": "tortas_expellers_pellets_harina_soja_pellets_harinas_tortas", + "dataset_identifier": "358", + "scrapingIdentifierCell": "C10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPTAS__59", + "scrapingDataStartCell": "C11" + }, + { + "distribution_identifier": "358.1", + "description": "Habas de soja, Los Demás, A granel con hasta un 15 % embolsado", + "title": "habas_soja_demas_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "D10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_HABAS_SOJAADO__52", + "scrapingDataStartCell": "D11" + }, + { + "distribution_identifier": "358.1", + "description": "Habas de soja, Los Demás, Más del 15 % embolsado", + "title": "habas_soja_demas_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "E10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_HABAS_SOJAADO__43", + "scrapingDataStartCell": "E11" + }, + { + "distribution_identifier": "358.1", + "description": "Aceite de soja, a granel", + "title": "aceite_soja_granel", + "dataset_identifier": "358", + "scrapingIdentifierCell": "F10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ACEITE_SOJNEL__18", + "scrapingDataStartCell": "F11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Los demás. En grano., A granel con hasta un 15 % embolsado", + "title": "maiz_demas_grano_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "G10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_DEMASADO__52", + "scrapingDataStartCell": "G11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Los demás. En grano., Más del 15 % embolsado", + "title": "maiz_demas_grano_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "H10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_DEMASADO__43", + "scrapingDataStartCell": "H11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Maíz Pisingallo, A granel con hasta un 15 % embolsado", + "title": "maiz_maiz_pisingallo_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "I10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_MAIZ_ADO__56", + "scrapingDataStartCell": "I11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Maíz Pisingallo, Más del 15 % embolsado", + "title": "maiz_maiz_pisingallo_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "J10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_MAIZ_ADO__47", + "scrapingDataStartCell": "J11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Flint o Plata, A granel con hasta un 15 % embolsado", + "title": "maiz_flint_plata_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "K10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_FLINTADO__52", + "scrapingDataStartCell": "K11" + }, + { + "distribution_identifier": "358.1", + "description": "Maíz, Flint o Plata, Más del 15 % embolsado", + "title": "maiz_flint_plata_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "L10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MAIZ_FLINTADO__43", + "scrapingDataStartCell": "L11" + }, + { + "distribution_identifier": "358.1", + "description": "Trigo Pan, Trigo Pan, A granel con hasta un 15 % embolsado", + "title": "trigo_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "M10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TRIGO_GRANADO__41", + "scrapingDataStartCell": "M11" + }, + { + "distribution_identifier": "358.1", + "description": "Trigo Pan, Trigo Pan, Más del 15 % embolsado", + "title": "trigo_pan_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "N10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TRIGO_PAN_ADO__36", + "scrapingDataStartCell": "N11" + }, + { + "distribution_identifier": "358.1", + "description": "Aceite de Girasol, a granel", + "title": "aceite_girasol_granel", + "dataset_identifier": "358", + "scrapingIdentifierCell": "O10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ACEITE_GIRNEL__21", + "scrapingDataStartCell": "O11" + }, + { + "distribution_identifier": "358.1", + "description": "Malta cervecera, Malta de cebada cervecera", + "title": "malta_cervecera_malta_cebada_cervecera", + "dataset_identifier": "358", + "scrapingIdentifierCell": "P10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_MALTA_CERVERA__38", + "scrapingDataStartCell": "P11" + }, + { + "distribution_identifier": "358.1", + "description": "Cebada, (no) Cervecera, A granel con hasta un 15 % embolsado", + "title": "cebada_cervecera_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "Q10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CEBADA_CERADO__52", + "scrapingDataStartCell": "Q11" + }, + { + "distribution_identifier": "358.1", + "description": "Cebada, Cervecera, Más del 15 % embolsado", + "title": "cebada_cervecera_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "R10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CEBADA_CERADO__43", + "scrapingDataStartCell": "R11" + }, + { + "distribution_identifier": "358.1", + "description": "Cacahuate o maní, Cacahuate o maní confitería y/o tostadero", + "title": "cacahuate_mani_confiteria_tostadero", + "dataset_identifier": "358", + "scrapingIdentifierCell": "S10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CACAHUATE_ERO__35", + "scrapingDataStartCell": "S11" + }, + { + "distribution_identifier": "358.1", + "description": "Cacahuate o maní, Los Demás, A granel con hasta un 15 % embolsado", + "title": "cacahuate_mani_demas_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "T10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CACAHUATE_ADO__56", + "scrapingDataStartCell": "T11" + }, + { + "distribution_identifier": "358.1", + "description": "Cacahuate o maní, Los Demás, Más del 15 % embolsado", + "title": "cacahuate_mani_demas_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "U10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CACAHUATE_ADO__47", + "scrapingDataStartCell": "U11" + }, + { + "distribution_identifier": "358.1", + "description": "Cacahuate o maní, Maní partido", + "title": "cacahuate_mani_mani_partido", + "dataset_identifier": "358", + "scrapingIdentifierCell": "V10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CACAHUATE_IDO__27", + "scrapingDataStartCell": "V11" + }, + { + "distribution_identifier": "358.1", + "description": "Cebada, Cervecera, A granel con hasta un 15 % embolsado", + "title": "cebada_cervecera_detalle_granel_hasta_15_porciento_embol", + "dataset_identifier": "358", + "scrapingIdentifierCell": "W10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CEBADA_CERADO_II__52", + "scrapingDataStartCell": "W11" + }, + { + "distribution_identifier": "358.1", + "description": "Cebada, Cervecera, en granel Más del 15 % embolsado", + "title": "cebada_cervecera_granel_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "X10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_CEBADA_CERADO_III__43", + "scrapingDataStartCell": "X11" + }, + { + "distribution_identifier": "358.1", + "description": "Arroz, Arroz Semiblanqueado o blanqueado incluso pulido o glaseado, - no parbolizado, contenido grano quebrado < o = al 10%", + "title": "arroz_no_parbolizado_cont_grano_quebrado_men_igual_10porc", + "dataset_identifier": "358", + "scrapingIdentifierCell": "Y10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARR_SB_B_PORC__59", + "scrapingDataStartCell": "Y11" + }, + { + "distribution_identifier": "358.1", + "description": "Arroz, Arroz Semiblanqueado o blanqueado incluso pulido o glaseado, - no parbolizado, contenido grano quebrado > al 10%", + "title": "arroz_puli_glas_no_parbo_cont_grano_quebrado_may_10porc", + "dataset_identifier": "358", + "scrapingIdentifierCell": "Z10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARR_SB_B_PORC__53", + "scrapingDataStartCell": "Z11" + }, + { + "distribution_identifier": "358.1", + "description": "Arroz, Arroz Semiblanqueado o blanqueado incluso pulido o glaseado. Los demás no parbolizados., - Contenido grano quebrado < o = al 10%", + "title": "arroz_pulido_glasaseado_cont_gra_quebr_men_igual_10porc", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AA10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARR_SB_B_PORC_II__59", + "scrapingDataStartCell": "AA11" + }, + { + "distribution_identifier": "358.1", + "description": "Arroz, Arroz Semiblanqueado o blanqueado incluso pulido o glaseado. Los demás no parbolizados., - Contenido grano quebrado > al 10%", + "title": "arroz_pulido_glaseado_contenido_grano_quebrado_may_10porc", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AB10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARR_SB_B_PORC_IV__53", + "scrapingDataStartCell": "AB11" + }, + { + "distribution_identifier": "358.1", + "description": "Harina de trigo, Harina de trigo", + "title": "harina_trigo", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AC10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_HARINA_TRIIGO__12", + "scrapingDataStartCell": "AC11" + }, + { + "distribution_identifier": "358.1", + "description": "Sorgo granífero, Los Demás, A granel con hasta un 15 % embolsado", + "title": "sorgo_granifero_demas_granel_hasta_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AD10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SORGO_GRANADO__57", + "scrapingDataStartCell": "AD11" + }, + { + "distribution_identifier": "358.1", + "description": "Sorgo granífero, Los Demás, Más del 15 % embolsado", + "title": "sorgo_granifero_demas_mas_15_porciento_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AE10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SORGO_GRANADO__48", + "scrapingDataStartCell": "AE11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Blancos Alubias, Ovales, En Envases mayores de 20 Kg.", + "title": "poro_blanc_alubias_ovales_envases_may_20_kg", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AF10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_PORO_BLANC_KG__43", + "scrapingDataStartCell": "AF11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Blancos, Alubias, En Envases mayores de 20 Kg. desde 191 y hasta 220 gramos cada 100 gramos", + "title": "poro_blanc_alubias_env_may_20_kg_dsd_191_hta_220_gr_c_100_gr", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AG10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_PORO_BLANC_GR__60", + "scrapingDataStartCell": "AG11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Blancos, Alubias, En Envases mayores de 20 Kg. desde 221 gramos por cada 100 gramos", + "title": "poro_blanc_alubias_env_may_20_kg_dsd_221_gr_cada_100_gr", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AH10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_PORO_BLANC_GR__55", + "scrapingDataStartCell": "AH11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Blancos, Alubias, En Envases mayores de 20 Kg. hasta 190 gramos por cada 100 gramos", + "title": "poro_blanc_alubias_env_may_20_kg_hta_190_gr_cada_100_gr", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AI10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_PORO_BLANC_GR_IVI__55", + "scrapingDataStartCell": "AI11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Negros, En Envases mayores de 20 Kg.", + "title": "poro_negros_envases_may_20_kg", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AJ10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_PORO_NEGRO_KG__29", + "scrapingDataStartCell": "AJ11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harinas de girasol, Tortas", + "title": "tortas_expellers_pellets_harinas_girasol_tortas", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AK10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPTAS__47", + "scrapingDataStartCell": "AK11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harinas de girasol, Harinas de tortas", + "title": "tortas_expellers_pellets_harinas_girasol_harinas_tortas", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AL10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPTAS__55", + "scrapingDataStartCell": "AL11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harinas de girasol, \"Pellets\", integral", + "title": "tortas_expellers_pellets_harinas_girasol_pellets_integral", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AM10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPRAL__57", + "scrapingDataStartCell": "AM11" + }, + { + "distribution_identifier": "358.1", + "description": "Tortas, \"Expellers\", \"Pellets\" y Harinas de girasol, \"Pellets\", de harina de extracción", + "title": "tortas_expellers_pellets_harinas_girasol_pellets_extr", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AN10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_TORTAS_EXPXTR__53", + "scrapingDataStartCell": "AN11" + }, + { + "distribution_identifier": "358.1", + "description": "Semilla de Girasol. Unicamente para industria, Los Demás, A granel con hasta un 15 % embolsado", + "title": "semilla_girasol_unica_ind_demas_granel_hta_15_porc_embol", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AO10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SEMILLA_GIBOL__56", + "scrapingDataStartCell": "AO11" + }, + { + "distribution_identifier": "358.1", + "description": "Semilla de Girasol. Unicamente para industria, Los Demás, Girasol, tipo confitería", + "title": "semilla_girasol_unica_ind_demas_girasol_tipo_confiteria", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AP10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SEMILLA_GIRIA__55", + "scrapingDataStartCell": "AP11" + }, + { + "distribution_identifier": "358.1", + "description": "Semilla de Girasol. Unicamente para industria, Los Demás, Más del 15 % embolsado", + "title": "semilla_girasol_unica_ind_demas_mas_15_por_embolsado", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AQ10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SEMILLA_GIADO__52", + "scrapingDataStartCell": "AQ11" + }, + { + "distribution_identifier": "358.1", + "description": "Aceite de cacahuete o maní, a granel", + "title": "aceite_cacahuete_mani_granel", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AR10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ACEITE_CACNEL__28", + "scrapingDataStartCell": "AR11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado B", + "title": "s_cardar_peinar_desmo_algo_grado_b", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AS10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_S_CARDAR_PO_B__34", + "scrapingDataStartCell": "AS11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado C", + "title": "algo_s_cardar_peinar_desmo_grado_c", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AT10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ALGO_S_CARO_C__34", + "scrapingDataStartCell": "AT11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado C 1/2", + "title": "s_cardar_peinar_desmo_grado_c_1_2", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AU10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_S_CARDAR_P1_2__33", + "scrapingDataStartCell": "AU11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado D 1/2 Long. 27,0 mm (1 1/16)", + "title": "s_cardar_peinar_desmo_grado_d_1_2_long_27_mm_1_1_16", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AV10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_S_CARDAR_P_16__51", + "scrapingDataStartCell": "AV11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado D Long. 27,0 mm (1 1/16)", + "title": "s_cardar_peinar_desmo_grado_d_long_27_mm_1_1_16", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AW10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_S_CARDAR_P_16__47", + "scrapingDataStartCell": "AW11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado E Long. 26,2 mm (1 1/32)", + "title": "s_cardar_peinar_desmotado_grado_long_26_mm_1_1_32", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AX10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_S_CARDAR_P_32__49", + "scrapingDataStartCell": "AX11" + }, + { + "distribution_identifier": "358.1", + "description": "Algodón s/cardar ni peinar simplemente desmotado, Algodón Grado F Long. 26,2 mm (1 1/32)", + "title": "sin_cardar_peinar_desmotado_grado_f_long_26_mm_1_1_32", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AY10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_SIN_CARDAR_32__53", + "scrapingDataStartCell": "AY11" + }, + { + "distribution_identifier": "358.1", + "description": "Garbanzos, Enteros", + "title": "garbanzos_enteros", + "dataset_identifier": "358", + "scrapingIdentifierCell": "AZ10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_GARBANZOS_ROS__17", + "scrapingDataStartCell": "AZ11" + }, + { + "distribution_identifier": "358.1", + "description": "Garbanzos, Partidos", + "title": "garbanzos_partidos", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BA10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_GARBANZOS_DOS__18", + "scrapingDataStartCell": "BA11" + }, + { + "distribution_identifier": "358.1", + "description": "Porotos, Colorados, En Envases mayores de 20 Kg.", + "title": "porotos_colorados_envases_mayores_20_kg", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BB10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_POROTOS_CO_KG__39", + "scrapingDataStartCell": "BB11" + }, + { + "distribution_identifier": "358.1", + "description": "Arvejas, Enteras", + "title": "arvejas_enteras", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BC10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARVEJAS_ENRAS__15", + "scrapingDataStartCell": "BC11" + }, + { + "distribution_identifier": "358.1", + "description": "Arvejas, Partidas", + "title": "arvejas_partidas", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BD10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARVEJAS_PADAS__16", + "scrapingDataStartCell": "BD11" + }, + { + "distribution_identifier": "358.1", + "description": "Aceite de Girasol, Los Demás, Refinado a granel", + "title": "aceite_girasol_demas_refinado_granel", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BE10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ACEITE_GIRNEL__36", + "scrapingDataStartCell": "BE11" + }, + { + "distribution_identifier": "358.1", + "description": "Aceite de Girasol, Los Demás, Refinado en tambores de mas de 200 litros", + "title": "aceite_girasol_demas_refinado_tambores_mas_200_litros", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BF10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ACEITE_GIRROS__53", + "scrapingDataStartCell": "BF11" + }, + { + "distribution_identifier": "358.1", + "description": "Arroz, Arroz descascarillado (arroz cargo o arroz pardo), Los demás. No parbolizado", + "title": "arroz_descascarillado_arroz_cargo_arroz_pardo_demas_no_parbo", + "dataset_identifier": "358", + "scrapingIdentifierCell": "BG10", + "units": "Dolares por tonelada", + "type": "number", + "id": "358.1_ARROZ_DESCRBO__60", + "scrapingDataStartCell": "BG11" + } + ], + "draft": false, + "identifier": "358.1", + "scrapingFileURL": "https://www.economia.gob.ar/download/infoeco/apendice5.xlsx" + } + ] + } + ], + "identifier": "sspm", + "spatial": "ARG", + "title": "Datos Programación Macroeconómica", + "themeTaxonomy": [ + { + "label": "Actividad", + "id": "actividad", + "description": "Series de actividad: cuentas nacionales, consumo, producción, etc." + }, + { + "label": "Empleo e Ingresos", + "id": "empleo", + "description": "Series de empleo e ingresos: mercado laboral, salarios, etc." + }, + { + "label": "Sector Externo", + "id": "externo", + "description": "Series externas: Balance de Pagos, Intercambio Comercial, etc." + }, + { + "label": "Dinero y Bancos", + "id": "moneda", + "description": "Series monetarias y bancarias" + }, + { + "label": "Precios", + "id": "precios", + "description": "Series de precios" + }, + { + "label": "Economía Internacional", + "id": "internacional", + "description": "Series económicas mundiales" + }, + { + "label": "Finanzas Públicas", + "id": "fiscal", + "description": "Series de recaudación, ingresos, gastos, etc." + }, + { + "label": "Mercados Financieros", + "id": "finanzas", + "description": "Series financieras y de mercado de capitales" + } + ] +} \ No newline at end of file diff --git a/series_tiempo_ar_api/apps/metadata/tests/tests.py b/series_tiempo_ar_api/apps/metadata/tests/tests.py index 7427f572..541662a4 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/tests.py @@ -80,7 +80,7 @@ def test_add_filter_no_param(self): self.assertEqual(prev_dict, search) -class IndexerTests(TestCase): +class CatalogIndexerTests(TestCase): def setUp(self): # No mandar datos a la instancia de ES @@ -108,3 +108,5 @@ def test_scraping_result(self): self.assertIn(key, mapping_fields) self.assertEqual(field['_index'], constants.FIELDS_INDEX) + + diff --git a/series_tiempo_ar_api/apps/metadata/tests/view_tests.py b/series_tiempo_ar_api/apps/metadata/tests/view_tests.py index d99a6ece..4b15b8e6 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/view_tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/view_tests.py @@ -63,3 +63,17 @@ def test_run(self): response_sources = json.loads(response.content)['data'] # Expected: search results in 'data' list self.assertIn(test_unit, response_sources) + + +class CatalogIDTests(TestCase): + + def test_run(self): + test_unit = 'Test_catalog_id' + search_mock = mock.MagicMock() + search_mock.aggregations.results.buckets = [{'key': test_unit}] + + with mock.patch.object(Search, 'execute', return_value=search_mock): + response = self.client.get(reverse('api:metadata:catalog_id')) + response_sources = json.loads(response.content)['data'] + # Expected: search results in 'data' list + self.assertIn(test_unit, response_sources) From f2ac5bda7f00e35e7b5faf02513018adee7076b3 Mon Sep 17 00:00:00 2001 From: Lucas Lavandeira <19612265+lucaslavandeira@users.noreply.github.com> Date: Wed, 13 Jun 2018 15:28:18 -0300 Subject: [PATCH 4/4] Fix codestyle --- series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py | 2 +- series_tiempo_ar_api/apps/metadata/tests/tests.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py b/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py index dd8ecf1a..db505f53 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/indexer_tests.py @@ -44,4 +44,4 @@ def test_index_two_nodes(self): self.assertTrue(second_catalog_fields) def tearDown(self): - self.elastic.indices.delete(self.FakeField._doc_type.index) \ No newline at end of file + self.elastic.indices.delete(self.FakeField._doc_type.index) diff --git a/series_tiempo_ar_api/apps/metadata/tests/tests.py b/series_tiempo_ar_api/apps/metadata/tests/tests.py index 541662a4..d691ff91 100644 --- a/series_tiempo_ar_api/apps/metadata/tests/tests.py +++ b/series_tiempo_ar_api/apps/metadata/tests/tests.py @@ -108,5 +108,3 @@ def test_scraping_result(self): self.assertIn(key, mapping_fields) self.assertEqual(field['_index'], constants.FIELDS_INDEX) - -