Normalmente podemos usar el comando mongoimport desde el shell para subir archivos JSON y Large también a mongodb y tendríamos nuestro esquema listo en la colección sin necesidad de preocuparnos por el tamaño máximo (16 MB) ya que mongo se encargará del tamaño del lote, etc. (esto ha sido probado y funcionado), y los datos estarán en filas y todo es genial.

El principal problema aquí es cómo hacer lo mismo con python usando pymongo y GridFS. Cuando estoy usando GridFS, se está cargando en un tipo diferente de colección (* .files) y el esquema no está definido como el primer método. Los archivos están en bytes y los nombres de las colecciones son * .files

Me gustaría saber cómo hacer el método python y obtener los resultados como con el comando mongoimport

Mi código es :

fs = gridfs.GridFS(db, collection='test_collection')
with open(path_to_big_json_file, 'rb') as dictionary:
    fs.put(dictionary, filename='test_filename')

Y los resultados son los siguientes:

enter image description here

Mi objetivo es tener el esquema listo inmediatamente en una colección normal y no en una colección GridFS como esa: ingrese la descripción de la imagen aquí

He intentado la inserción masiva en pymongo y no ha funcionado ya que el archivo era tan grande, estoy seguro de que habría una forma, no es necesario usar GridFS, pero manténgalo en python

¡Gracias!

0
Arrajj 26 nov. 2019 a las 19:57

1 respuesta

La mejor respuesta

Bien, he creado una función que divide el marco de datos y los guarda temporalmente para insertarlo más tarde.

Funciona al escalar cada marco de datos a partes de menos de 16 MB en un 10 por ciento, luego ingerimos eso

P.S: es para GeoJSON

def insert_geojson_in_batches_to_mongo(mongoclient, db, collection_name, origin_path, threshold=10):

  df = gpd.read_file(transformed_path)
  file_size = os.path.getsize(origin_path)
  max_size = mongoclient.max_bson_size
  number_of_dataframes = ceil(file_size*(1+threshold/100) / max_size)
  df_len = len(df)
  number_of_rows_per_df = floor(df_len/number_of_dataframes)
  collection = db.get_collection(collection_name)

  with tempfile.TemporaryDirectory() as tmpdirname:
    count = 0
    k = 0
    while True:
      if count > df_len-1:
            break          
      filename = tmpdirname + 'df' + str(count) + '.geojson'
      start = count
      count += number_of_rows_per_df  
      k += 1
      df.iloc[start : count].to_file(filename, driver="GeoJSON")      
      with open(filename) as f: 
        data = json.load(f)  
      data = data['features']
      print('bulk {0}/{1} is being loaded'.format(k , number_of_dataframes+1))
      collection.insert_many(data)
0
Khaled arja 27 nov. 2019 a las 15:33