Làm cách nào để xuất bộ sưu tập MongoDB sang CSV bằng Python?

Tôi có một tập lệnh Python để tạo danh sách các phiên bản EC2 trong tất cả các tài khoản AWS của chúng tôi [khoảng 150] và lưu trữ kết quả trong MongoDB

Tôi đang xuất bộ sưu tập mongodb sang tệp CSV bằng mô-đun gấu trúc Python. Nó hoạt động ngoại trừ các tiêu đề không theo thứ tự và tôi không muốn in Chỉ mục MongoDB

Trong phiên bản gốc của tập lệnh [trước khi thêm cơ sở dữ liệu], tôi đã sử dụng mô-đun CSV để ghi tệp và các tiêu đề đều chính xác.

Tôi đã thêm cơ sở dữ liệu như một bài tập học tập và vì nó giúp làm việc dễ dàng hơn với tất cả các tài khoản Amazon mà chúng tôi có

Nếu tôi xem json trong cơ sở dữ liệu mongo cho bộ sưu tập, tôi đang in tất cả các trường theo đúng thứ tự

{'_id': ObjectId['5f14f9ffa40de31278dade03'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb001', 'Instance ID': 'i-01e5e920b4d3d5dcb', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-0ce8db4e071bc7229, vol-099f6d212a91121d0, vol-0bb36e343e9c01374, vol-05610645edfd02253, vol-05adc01d70d75d649', 'Private IP': '172.31.62.168', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-62-168.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}
{'_id': ObjectId['5f14f9ffa40de31278dade05'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb002', 'Instance ID': 'i-0b7db2bcab853ef96', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-095a9dcf54ca97c0e, vol-0c8e96b71fbb7dfcf, vol-070c16c457f91c54e, vol-0dc1eaf2e826fa3a6, vol-0f0f157a8489ab939', 'Private IP': '172.31.63.131', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-63-131.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}
{'_id': ObjectId['5f14f9ffa40de31278dade07'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb003', 'Instance ID': 'i-0611acf4b6cc53b61', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-0aa28f89f6ce50577, vol-0e37ff844e8b9c47a, vol-0d54c713ae231739c, vol-0e29df46edc814619, vol-07e0c40a8913b1d31', 'Private IP': '172.31.52.44', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-52-44.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}

Nhưng sử dụng gấu trúc python để xuất từ ​​​​cơ sở dữ liệu mongo, các tiêu đề đã hết tác dụng. Dòng thông tin đến đúng tiêu đề, nhưng các cột hoàn toàn không theo thứ tự

Trong mã của tôi, tôi đang tạo một từ điển có thông tin máy chủ trong đó, sau đó chuyển từ điển sang hàm in bộ sưu tập Mongo

def list_instances[aws_account,aws_account_number, interactive, regions, show_details, instance_col]:
for region in regions:
    if 'gov' in aws_account and not 'admin' in aws_account:
        try:
            session = boto3.Session[profile_name=aws_account, region_name=region]
        except botocore.exceptions.ProfileNotFound as e:
            profile_missing_message = f"An exception has occurred: {e}"
            account_found = 'no'
            raise
    else:
        try:
            session = boto3.Session[profile_name=aws_account, region_name=region]
            account_found = 'yes'
        except botocore.exceptions.ProfileNotFound as e:
            profile_missing_message = f"An exception has occurred: {e}"
            raise
    try:
        ec2 = session.client["ec2"]
    except Exception as e:
        print[f"An exception has occurred: {e}"]
    message = f"  Region: {region} in {aws_account}: [{aws_account_number}]  "
    banner[message]

    print[Fore.RESET]
    # Loop through the instances
    try:
        instance_list = ec2.describe_instances[]
    except Exception as e:
        print[f"An exception has occurred: {e}"]
        for reservation in instance_list["Reservations"]:
                for instance in reservation.get["Instances", []]:
                    instance_count = instance_count + 1
                    launch_time = instance["LaunchTime"]
                    launch_time_friendly = launch_time.strftime["%B %d %Y"]
                    tree = objectpath.Tree[instance]
                    block_devices = set[tree.execute['$..BlockDeviceMappings[\'Ebs\'][\'VolumeId\']']]
                    if block_devices:
                        block_devices = list[block_devices]
                        block_devices = str[block_devices].replace['[',''].replace[']',''].replace['\'','']
                    else:
                        block_devices = None
                    private_ips =  set[tree.execute['$..PrivateIpAddress']]
                    if private_ips:
                        private_ips_list = list[private_ips]
                        private_ips_list = str[private_ips_list].replace['[',''].replace[']',''].replace['\'','']
                    else:
                        private_ips_list = None
                    public_ips =  set[tree.execute['$..PublicIp']]
                    if len[public_ips] == 0:
                        public_ips = None
                    if public_ips:
                        public_ips_list = list[public_ips]
                        public_ips_list = str[public_ips_list].replace['[',''].replace[']',''].replace['\'','']
                    else:
                        public_ips_list = None
                    name = None
                    if 'Tags' in instance:
                        try:
                            tags = instance['Tags']
                            name = None
                            for tag in tags:
                                if tag["Key"] == "Name":
                                    name = tag["Value"]
                                if tag["Key"] == "Engagement" or tag["Key"] == "Engagement Code":
                                    engagement = tag["Value"]
                        except ValueError:
                            # print["Instance: %s has no tags" % instance_id]
                            raise
                    key_name = instance['KeyName'] if instance['KeyName'] else None
                    vpc_id = instance.get['VpcId'] if instance.get['VpcId'] else None
                    private_dns = instance['PrivateDnsName'] if instance['PrivateDnsName'] else None
                    ec2info[instance['InstanceId']] = {
                        'AWS Account': aws_account,
                        'Account Number': aws_account_number,
                        'Name': name,
                        'Instance ID': instance['InstanceId'],
                        'AMI ID': instance['ImageId'],
                        'Volumes': block_devices,
                        'Private IP': private_ips_list,
                        'Public IP': public_ips_list,
                        'Private DNS': private_dns,
                        'Availability Zone': instance['Placement']['AvailabilityZone'],
                        'VPC ID': vpc_id,
                        'Type': instance['InstanceType'],
                        'Key Pair Name': key_name,
                        'State': instance['State']['Name'],
                        'Launch Date': launch_time_friendly
                    }
                    mongo_instance_dict = {'_id': '', 'AWS Account': aws_account, "Account Number": aws_account_number, 'Name': name, 'Instance ID': instance["InstanceId"], 'AMI ID': instance['ImageId'], 'Volumes': block_devices,  'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance["InstanceType"], 'Key Pair Name': key_name, 'State': instance["State"]["Name"], 'Launch Date': launch_time_friendly}
                    insert_doc[mongo_instance_dict]
    mongo_export_to_file[interactive, aws_account]

Đây là chức năng chèn từ điển vào MongoDB

def insert_doc[mydict]:
    mydb, mydb_name, instance_col = set_db[]
    mydict['_id'] = ObjectId[]
    instance_doc = instance_col.insert_one[mydict]
    return instance_doc

Đây là chức năng ghi MongoDB vào tệp

def mongo_export_to_file[]:
    aws_account = 'jf-master-pd'
    today = datetime.today[]
    today = today.strftime["%m-%d-%Y"]
    mydb, mydb_name, instance_col = set_db[]
    # make an API call to the MongoDB server
    cursor = instance_col.find[]
    # extract the list of documents from cursor obj
    mongo_docs = list[cursor]

    # create an empty DataFrame for storing documents
    docs = pandas.DataFrame[columns=[]]

    # iterate over the list of MongoDB dict documents
    for num, doc in enumerate[mongo_docs]:
        # convert ObjectId[] to str
        doc["_id"] = str[doc["_id"]]
        # get document _id from dict
        doc_id = doc["_id"]
        # create a Series obj from the MongoDB dict
        series_obj = pandas.Series[ doc, name=doc_id ]
         # append the MongoDB Series obj to the DataFrame obj
        docs = docs.append[series_obj]
        # get document _id from dict
        doc_id = doc["_id"]
        # Set the output file
        output_dir = os.path.join['..', '..', 'output_files', 'aws_instance_list', 'csv', '']
        output_file = os.path.join[output_dir, 'aws-instance-master-list-' + today +'.csv']

        # export MongoDB documents to a CSV file
        docs.to_csv[output_file, ","] # CSV delimited by commas

Đây là một liên kết đến thư mục mã gốc trong github. Các tệp chúng tôi muốn là aws_ec2_list_instances. py và ec2_mongo. py

Tại sao các cột và tiêu đề không theo thứ tự trong phiên bản MongoDB?

Pandas là một thư viện rất linh hoạt và linh hoạt để quản lý và phân tích dữ liệu. Sẽ là quá mức cần thiết nếu tất cả những gì bạn muốn làm là chuyển đổi bộ sưu tập MongoDB thành tệp CSV khi mô-đun csv đạt tiêu chuẩn và cách bạn đang sử dụng nó rất kém hiệu quả. Một điều khác cần lưu ý là cho đến gần đây, cả Python và Pandas đều không cố gắng duy trì thứ tự của các mục trong một lệnh. Trước khi Python bắt đầu giữ trật tự trong phiên bản 3. 5, mã được viết dựa trên giả định rằng thứ tự của các mục trong lệnh là không quan trọng. Chỉ kể từ Python 3. 7 việc duy trì thứ tự của các mục chính tả có trở thành một tính năng ngôn ngữ chính thức không

DataFrame là cấu trúc dữ liệu chính của Pandas và nó đại diện cho một mảng dữ liệu 2 chiều. Một số điều về nó có thể gây nhầm lẫn và tôi nghĩ rằng bạn đã vấp phải sự thật là cả hàng và cột đều có thể có các chỉ mục được đặt tên. Nói chung, khi nói về dữ liệu trong Panda, "index" đề cập đến chỉ số hàng

Trong dữ liệu của bạn, chỉ mục hàng sẽ là giá trị của MongoDB _id và bạn muốn vứt nó đi. Điều đó tốt, nhưng nó có thể khiến bạn nghĩ rằng "chỉ mục" có nghĩa là cột

Một Sê-ri thường có nghĩa là đại diện cho một cột dữ liệu. Khi được khởi tạo bằng lệnh, các khóa được coi là chỉ mục, nghĩa là nhãn hàng chứ không phải nhãn cột. Bạn sẽ thấy hầu hết các hoạt động giữa DataFrames và Sê-ri đều coi Sê-ri là cột. Nhưng như tôi đã nói, Pandas rất linh hoạt, vì vậy chúng có hàm DataFrame.append coi Sê-ri là một hàng

Điều hấp dẫn là khi nối thêm một hàng, Pandas mong muốn Sê-ri sẽ nối thêm một hàng vào các cột hiện có. Khi Sê-ri có các chỉ mục [các khóa trong lệnh gốc] không tồn tại trong DataFrame, nó sẽ thêm chúng vào cuối các cột dưới dạng cột mới và như bạn thấy, nó sẽ thêm chúng theo thứ tự được sắp xếp. Đây thực sự là một lỗi trong phiên bản hiện tại [1. 0. 5] điều đó có lẽ đã được phép kéo dài đến mức này mà không được sửa chữa vì dù sao thì lệnh dict đã từng bị bỏ qua, nhưng hãy biết ơn vì điều đó, vì nó đã khiến bạn phải điều tra thêm

Việc bạn chuyển đổi bộ sưu tập MongoDB thành DataFrame bằng cách nối thêm Sê-ri vào DataFrame trống ban đầu thực sự không hiệu quả. DataFrame hoàn toàn có khả năng đọc bộ sưu tập MongoDB của bạn và thực hiện điều đó với ít mã hơn để bạn viết

Chủ Đề