如何使用 pymongo 迭代或删除 MongoDb 数组列表项?
How Iterate or remove MongoDb array list item using pymongo?
我想迭代 Mongodb 数据库 Arraylist 项目(TRANSACTION 列表)并使用 pymongo 删除特定于 Arraylist(TRANSACTION 列表)的项目?
我使用 python pymongo 创建了 Mongo 集合。我想使用 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'
要删除最后一个条目,一般的想法(如您所提到的)是迭代数组并获取最后一个元素的索引,如其 DATE
字段所示,然后通过删除更新集合它使用 $pull
。因此,您需要的关键数据是 DATE
值和文档的 _id
.
您可以采用的一种方法是首先使用聚合框架来获取此数据。有了这个,您可以 运行 一个管道,其中第一步是使用 $match
运算符过滤集合中的文档,该运算符使用标准 MongoDB查询。
过滤文档后的下一阶段是展平 TRANSACTION
数组,即对列表中的文档进行非规范化,以便您可以过滤最终项目,即通过 DATE
字段获取最后一个文档.这可以通过 $unwind
运算符实现,对于每个输入文档,输出 n 个文档,其中 n 是数组元素的数量,对于空数组可以为零。
数组解构后,为了得到最后一个文档,使用$group
operator where you can regroup the flattened documents and in the process use the group accumulator运算符得到
最后一个 TRANSACTION
日期,使用应用于其嵌入的 DATE
字段的 $max
运算符。
所以本质上,运行下面的管道并使用结果来更新集合。例如,您可以 运行 以下管道:
mongo shell
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"]
}
}
}
)
python
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
管道更新您的集合,该管道将管道的结果写入同系列:
If the collection specified by the $out
operation already
exists, then upon completion of the aggregation, the $out
stage atomically replaces the existing collection with the new results collection. The $out
operation does not
change any indexes that existed on the previous collection. If the
aggregation fails, the $out
operation makes no changes to
the pre-existing collection.
例如,您可以 运行 这个管道:
mongo shell
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" }
])
python
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" }
])
虽然这种方法比第一种方法更有效,但它需要先了解现有领域,因此在某些情况下,解决方案并不实用。
我想迭代 Mongodb 数据库 Arraylist 项目(TRANSACTION 列表)并使用 pymongo 删除特定于 Arraylist(TRANSACTION 列表)的项目?
我使用 python pymongo 创建了 Mongo 集合。我想使用 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'
要删除最后一个条目,一般的想法(如您所提到的)是迭代数组并获取最后一个元素的索引,如其 DATE
字段所示,然后通过删除更新集合它使用 $pull
。因此,您需要的关键数据是 DATE
值和文档的 _id
.
您可以采用的一种方法是首先使用聚合框架来获取此数据。有了这个,您可以 运行 一个管道,其中第一步是使用 $match
运算符过滤集合中的文档,该运算符使用标准 MongoDB查询。
过滤文档后的下一阶段是展平 TRANSACTION
数组,即对列表中的文档进行非规范化,以便您可以过滤最终项目,即通过 DATE
字段获取最后一个文档.这可以通过 $unwind
运算符实现,对于每个输入文档,输出 n 个文档,其中 n 是数组元素的数量,对于空数组可以为零。
数组解构后,为了得到最后一个文档,使用$group
operator where you can regroup the flattened documents and in the process use the group accumulator运算符得到
最后一个 TRANSACTION
日期,使用应用于其嵌入的 DATE
字段的 $max
运算符。
所以本质上,运行下面的管道并使用结果来更新集合。例如,您可以 运行 以下管道:
mongo shell
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"]
}
}
}
)
python
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
管道更新您的集合,该管道将管道的结果写入同系列:
If the collection specified by the
$out
operation already exists, then upon completion of the aggregation, the$out
stage atomically replaces the existing collection with the new results collection. The$out
operation does not change any indexes that existed on the previous collection. If the aggregation fails, the$out
operation makes no changes to the pre-existing collection.
例如,您可以 运行 这个管道:
mongo shell
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" }
])
python
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" }
])
虽然这种方法比第一种方法更有效,但它需要先了解现有领域,因此在某些情况下,解决方案并不实用。