Как перебрать или удалить элемент списка массива MongoDb с помощью pymongo?

Я хочу перебирать элементы Arraylist базы данных Mongodb (список транзакций) и удалять определенный элемент Arraylist (список транзакций), используя pymongo?

введите здесь описание изображения

Я создаю коллекцию Mongo, как указано выше, используя python pymongo. Я хочу перебрать элемент списка массива с помощью pymongo и удалить последний элемент только в Arraylist?

Запрос на вставку данных с использованием Python pymongo

 # added new method  create block chain_structure
    def addCoinWiseTransaction(self, senz, coin, format_date):
        self.collection = self.db.block_chain
        coinValexists = self.collection.find({"_id": str(coin)}).count()
        print('coin exists : ', coinValexists)
        if (coinValexists > 0):
            print('coin hash exists')
            newTransaction = {"$push": {"TRANSACTION": {"SENDER": senz.attributes["#SENDER"],
                                                        "RECIVER": senz.attributes["#RECIVER"],
                                                        "T_NO_COIN": int(1),
                                                        "DATE": datetime.datetime.utcnow()
                                                        }}}
            self.collection.update({"_id": str(coin)}, newTransaction)
        else:
            flag = senz.attributes["#f"];
            print flag
            if (flag == "ccb"):
                print('new coin mined othir minner')
                root = {"_id": str(coin)
                    , "S_ID": int(senz.attributes["#S_ID"]), "S_PARA": senz.attributes["#S_PARA"],
                        "FORMAT_DATE": format_date,
                        "NO_COIN": int(1),
                        "TRANSACTION": [{"MINER": senz.attributes["#M_S_ID"],
                                         "RECIVER": senz.attributes["#RECIVER"],
                                         "T_NO_COIN": int(1),
                                         "DATE": datetime.datetime.utcnow()
                                         }
                                        ]
                        }
                self.collection.insert(root)
            else:
                print('new coin mined')
                root = {"_id": str(coin)
                    , "S_ID": int(senz.attributes["#S_ID"]), "S_PARA": senz.attributes["#S_PARA"],
                        "FORMAT_DATE": format_date,
                        "NO_COIN": int(1),
                        "TRANSACTION": [{"MINER": "M_1",
                                         "RECIVER": senz.sender,
                                         "T_NO_COIN": int(1),
                                         "DATE": datetime.datetime.utcnow()
                                         }
                                        ]
                        }
                self.collection.insert(root)

        return 'DONE'

person uma    schedule 06.01.2017    source источник
comment
Было бы лучше включить запрос/вывод в это изображение как фактический текст в ваш вопрос.   -  person Tagc    schedule 06.01.2017
comment
Вы хотите обновить для каждого документа в вашей коллекции?   -  person chridam    schedule 06.01.2017
comment
@chridam нет, когда я даю идентификатор, достаточно обновить этот кортеж.   -  person uma    schedule 06.01.2017


Ответы (1)


Чтобы удалить последнюю запись, общая идея (как вы упомянули) состоит в том, чтобы перебрать массив и получить индекс последнего элемента, обозначенный его полем DATE, а затем обновить коллекцию, удалив ее с помощью $pull. Таким образом, ключевой элемент данных, который вам нужен для работы, — это значение DATE и значение _id документа.

Один из возможных подходов — сначала использовать структуру агрегации для получения этих данных. При этом вы можете запустить конвейер, где первым шагом будет фильтрация документов в коллекции с помощью $match, использующий стандартные запросы MongoDB.

Следующим этапом после фильтрации документов является выравнивание массива TRANSACTION, т. е. денормализация документов в списке, чтобы можно было отфильтровать конечный элемент, т. е. получить последний документ по полю DATE. Это стало возможным благодаря $unwind, который для каждого входного документа выводит n документов, где n — количество элементов массива и может быть равно нулю для пустого массива.

После деконструкции массива, чтобы получить последний документ, используйте ссылку $group, где вы можете перегруппировать сведенные документы и в процессе использовать группу накопитель для получения последней TRANSACTION даты с помощью $max применяется к встроенному полю DATE.

По сути, запустите следующий конвейер и используйте результаты для обновления коллекции. Например, вы можете запустить следующий конвейер:

оболочка монго

db.block_chain.aggregate([
    { "$match": { "_id": coin_id } },
    { "$unwind": "$TRANSACTION" },
    { 
        "$group": {
            "_id": "$_id",
            "last_transaction_date": { "$max": "$TRANSACTION.DATE" }
        }
    }
])

Затем вы можете получить документ с данными обновления из этой агрегированной операции, используя toArray() или совокупный курсор и обновите свою коллекцию:

var docs = db.block_chain.aggregate([
    { "$match": { "_id": coin_id } },
    { "$unwind": "$TRANSACTION" },
    { 
        "$group": {
            "_id": "$_id",
            "LAST_TRANSACTION_DATE": { "$max": "$TRANSACTION.DATE" }
        }
    }
]).toArray()

db.block_chain.updateOne(
    { "_id": docs[0]._id },
    { 
        "$pull": { 
            "TRANSACTION": { 
                "DATE": docs[0]["LAST_TRANSACTION_DATE"] 
            } 
        } 
    }
)

питон

def remove_last_transaction(self, coin):
    self.collection = self.db.block_chain

    pipe = [
        { "$match": { "_id": str(coin) } },
        { "$unwind": "$TRANSACTION" },
        { 
            "$group": {
                "_id": "$_id",
                "last_transaction_date": { "$max": "$TRANSACTION.DATE" }
            }
        }
    ]

    # run aggregate pipeline
    cursor = self.collection.aggregate(pipeline=pipe)
    docs = list(cursor)

    # run update
    self.collection.update_one(
        { "_id": docs[0]["_id"] },
        { 
            "$pull": { 
                "TRANSACTION": { 
                    "DATE": docs[0]["LAST_TRANSACTION_DATE"] 
                } 
            } 
        }
    )

Кроме того, вы можете запустить одну агрегатную операцию, которая также обновит вашу коллекцию с помощью $out конвейер, который записывает результаты конвейера в ту же коллекцию:

Если коллекция указана в $out уже существует, то после завершения агрегации $out атомарно заменяет существующую коллекцию новой коллекцией результатов. $out операция не изменяет никакие индексы, существовавшие в предыдущей коллекции. Если агрегация не удалась, $out операция не вносит изменений в уже существующую коллекцию.

Например, вы можете запустить этот конвейер:

оболочка монго

db.block_chain.aggregate([
    { "$match": { "_id": coin_id } },
    { "$unwind": "$TRANSACTION" },
    { "$sort": { "TRANSACTION.DATE": 1 } }
    { 
        "$group": {
            "_id": "$_id",
            "LAST_TRANSACTION": { "$last": "$TRANSACTION" },
            "FORMAT_DATE": { "$first": "$FORMAT_DATE" },
            "NO_COIN": { "$first": "$NO_COIN" },
            "S_ID": { "$first": "$S_ID" },
            "S_PARA": { "$first": "$S_PARA" },
            "TRANSACTION": { "$push": "$TRANSACTION" }
        }
    },
    {
        "$project": {
            "FORMAT_DATE": 1,
            "NO_COIN": 1,
            "S_ID": 1,
            "S_PARA": 1,
            "TRANSACTION": { 
                "$setDifference": ["$TRANSACTION", ["$LAST_TRANSACTION"]]
            }
        }
    },
    { "$out": "block_chain" }
])

питон

def remove_last_transaction(self, coin):    
    self.db.block_chain.aggregate([
        { "$match": { "_id": str(coin) } },
        { "$unwind": "$TRANSACTION" },
        { "$sort": { "TRANSACTION.DATE": 1 } },
        { 
            "$group": {
                "_id": "$_id",
                "LAST_TRANSACTION": { "$last": "$TRANSACTION" },
                "FORMAT_DATE": { "$first": "$FORMAT_DATE" },
                "NO_COIN": { "$first": "$NO_COIN" },
                "S_ID": { "$first": "$S_ID" },
                "S_PARA": { "$first": "$S_PARA" },
                "TRANSACTION": { "$push": "$TRANSACTION" }
            }
        },
        {
            "$project": {
                "FORMAT_DATE": 1,
                "NO_COIN": 1,
                "S_ID": 1,
                "S_PARA": 1,
                "TRANSACTION": { 
                    "$setDifference": ["$TRANSACTION", ["$LAST_TRANSACTION"]]
                }
            }
        },
        { "$out": "block_chain" }
    ])

Хотя этот подход может быть более эффективным, чем первый, он требует сначала знания существующих полей, поэтому в некоторых случаях решение не может быть практичным.

person chridam    schedule 06.01.2017
comment
Спасибо, я буду кодировать, используя python, и подключаться к mongo db, используя pymongo, это код python? - person uma; 06.01.2017
comment
Нет, это код, который вы можете запустить на сервере в оболочке mongo. Концепции не так уж отличаются, хотя с драйвером pymongo. - person chridam; 06.01.2017
comment
попробуйте второй метод, 1 приходит синтаксическая ошибка, но когда я ставлю запятую (,) после '{ $sort: {TRANSACTION.DATE: 1 } }' этой строки, ошибка исчезла, но когда я запускаю код, который он дал, это ошибка . {$out: {block_chain}} exceptions.TypeError: unhashable type: 'dict' ? - person uma; 06.01.2017
comment
1-е решение также, ошибка передачи, повышение TypeError (конвейер должен быть списком) исключений. TypeError: конвейер должен быть списком в # запустить совокупную конвейерную линию? - person uma; 06.01.2017
comment
Плохо, мне удалось исправить опечатки. Написал это в один миг без надлежащего тестирования, поэтому обратите внимание, что это может вызвать некоторые ошибки, но я думаю, что вы сможете извлечь некоторые полезные концепции из ответа, надеюсь, :) - person chridam; 06.01.2017
comment
@childam, я постараюсь исправить это. - person uma; 06.01.2017
comment
@childam, я могу добиться успеха с помощью метода 1. - person uma; 07.01.2017