I have array:
{'_id': ObjectId('7262718c217dda3ad90ef151'), 'SomeText': "aaa", 'items': [{'status': 500, 'x': 1, 'y': None, 'price': 3}, { 'status': 500, 'x': 2, 'y': None, 'price': 4}]}
{'_id': ObjectId('7262718c217dda3ad90ef152'), 'SomeText': "bbb", 'items': [{'status': 300, 'x': 1, 'y': 2, 'price': 7}, { 'status': 500, 'x': 2, 'y': 2, 'price': 5}]}
{'_id': ObjectId('7262718c217dda3ad90ef153'), 'SomeText': "ccc", 'items': [{'status': 300, 'x': 1, 'y': 1, 'price': 8}]}
I need to find documents only those values where x not equal y and only field "SomeText", "х", "y"
Query:
fx = mycol.find({"$expr": {"$ne": ["$items.x", "$items.y"]}},
{ "_id": 0, "SomeText": 1, "items.x": 1, "items.y": 1, }
).limit(3)
for x in fx:
print(x)
Returns document with ALL array items in shapes,but I'd like to get the document only with the array that contains x not equal y
{'SomeText': "aaa" 'items': [{'x': 1, 'y': None,}, {'x': 2, 'y': None,}]}
{'SomeText': "bbb", 'items': [{'x': 1, 'y': 2}, {'x': 2, 'y': 2]}
Query:
fx=mycol.aggregate([
{"$match": {"$expr": {"$ne": ["$items.x", "$items.y"]}}},
{"$project": {
"items": {"$filter": {
"input": '$items',
"as": 'item',
"cond": {"$ne": ["$$item.x", "$$item.y"]}
}},
"_id": 0, "SomeText": 1
}},
{"$limit" : 5}
])
for x in fx:
print(x)
Returns document with "status" and "price"
{'SomeText': "aaa", 'items': [{'status': 500, 'x': 1, 'y': None, 'price': 3}, { 'status': 500, 'x': 2, 'y': None, 'price': 4}]}
{'SomeText': "bbb", 'items': [{'status': 300, 'x': 1, 'y': 2, 'price': 7}]}
Can I filter element in array to get result?
{'SomeText': "aaa", 'items': [{'x': 1, 'y': None,}, {'x': 2, 'y': None,}]}
{'SomeText': "bbb", 'items': [{'x': 1, 'y': 2}]}
CodePudding user response:
Just add a $map
step to your current query:
db.collection.aggregate([
{
$match: {$expr: {$ne: ["$items.x", "$items.y"]}}
},
{
$project: {
items: {
$filter: {
input: "$items",
as: "item",
cond: {$ne: ["$$item.x", "$$item.y"]}
}
},
_id: 0,
SomeText: 1
}
},
{
$set: {
items: {
$map: {
input: "$items",
as: "item",
in: {x: "$$item.x", y: "$$item.y"}
}
}
}
},
{
$limit: 5
}
])
See how it works on the playground example