I have a collection with a following data:
{
"_id" : ObjectId("4e3951905e746b3805000000"),
"m" : "hello",
"r" : [{
"_id" : ObjectId("4e3951965e746b8007000000"),
"u" : 3,
"m" : "response1"
}, {
"_id" : ObjectId("4e39519d5e746bc00f000000"),
"u" : 3,
"m" : "response2"
}, {
"_id" : ObjectId("4e3953dc5e746b5c07000000"),
"u" : 3,
"m" : "response3"
}, {
"_id" : ObjectId("4e3953ea5e746bd40f000001"),
"u" : 3,
"m" : "response"
}],
"u" : 3,
"w" : 3
}
{
"_id" : ObjectId("4e3952c75e746bd807000001"),
"m" : "asdfa",
"r" : [{
"_id" : ObjectId("4e39544e5e746bc00f000001"),
"u" : 3,
"m" : "response5"
}],
"u" : 3,
"w" : 3
}
Can anyone suggest how to remove a subdocument from a 'r' key
having only id of subdocument, I am going to del?
for instance i want to del a subdocument with id 4e39519d5e746bc00f000000
So this subdocument should be deleted
{
"_id" : ObjectId("4e39519d5e746bc00f000000"),
"u" : 3,
"m" : "response2"
},
It's easy, you just need to use $pull operator:
db.items.update( {},
{ $pull : { r : {"_id": ObjectId("4e39519d5e746bc00f000000")} } }, false, false )
dbh.users.update({"_id": ObjectId("4e39519d5e746bc00f000000")}, {"$unset":{"r":1}},False,False)
Try using unset
Reference: MongoDB : Update Modifier semantics of "$unset"
Related
The mongo documentation on update change events says that the update description will have an array of removed fields, a document of update fields and an array of truncated arrays. The removed and updated fields are pretty straight forward, but I'm having trouble understanding what the truncated arrays are.
The documentation says
An array of documents which record array truncations performed with
pipeline-based updates using one or more of the following stages:
$addFields
$set
$replaceRoot
$replaceWith
But try as I might, I can't seem to figure out how to even cause an update event that includes truncated arrays.
Any help understanding what this field is for and / or an example of how to cause an update that includes it would be greatly appreciated.
I did not know that the change stream document had truncatedArrays field. So, I tried to set up the change stream in MongoDB version 4 and 5.
MongoDB Enterprise rs0:PRIMARY> db.coll.find();
{ "_id" : ObjectId("63b2d783"), "a" : 1, "b" : [ { "c" : 1, "d" : "qwq" }, { "c" : 2, "d" : "mlo" } ] }
{ "_id" : ObjectId("63b2d784"), "a" : 2, "b" : [ { "c" : 4, "d" : "hyt" }, { "c" : 5, "d" : "nhw" } ] }
In another window,
MongoDB Enterprise rs0:PRIMARY> cs = db.coll.watch([], {"fullDocument": "updateLookup"});
MongoDB Enterprise rs0:PRIMARY> while(!cs.isExhausted()){
... if(cs.hasNext()){
... print(tojson(cs.next()));
... }
... }
Then I ran an update.
MongoDB Enterprise rs0:PRIMARY> db.coll.update({},{$set:{"a":3}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
There was no such field in the change stream.
{
"_id" : {"_data" : "8263B2D474000000012B022C0100296E5A100439C39"},
"operationType" : "update",
"clusterTime" : Timestamp(1672664180, 1),
"fullDocument" : {
"_id" : ObjectId("63b2d783"),
"a" : 3,
"b" : [
{"c" : 1,"d" : "qwq"},
{"c" : 2,"d" : "mlo"}
]
},
"ns" : {
"db" : "test","coll" : "coll"
},
"documentKey" : {"_id" : ObjectId("63b2d783")},
"updateDescription" : {
"updatedFields" : {
"a" : 3
},
"removedFields" : [ ]
}
}
Next, I updated the server to version 6 and executed this update query to slice the array.
db.coll.update(
{},
[
{$set: {"b": {$slice: ["$b",1]}}}
]
);
And, there it was. Showing the array field name and it's new size.
{
"_id" : {"_data" : "8263B2D756000000012B022C0100296E5A1004A7FD82"},
"operationType" : "update",
"clusterTime" : Timestamp(1672664918, 1),
"wallTime" : ISODate("2023-01-02T13:08:38.584Z"),
"fullDocument" : {
"_id" : ObjectId("63b2d1d6"),
"a" : 1,
"b" : [
{"c" : 1,"d" : "qwq"}
]
},
"ns" : {
"db" : "test","coll" : "coll"
},
"documentKey" : {"_id" : ObjectId("63b2d1d6")},
"updateDescription" : {
"updatedFields" : {
},
"removedFields" : [ ],
"truncatedArrays" : [
{
"field" : "b",
"newSize" : 1
}
]
}
}
I couldn't find any other way to cause this using $replaceRoot/$replaceWith.
I need to execute the following query:
db.S12_RU.find({"venue.raw":a,"title":/b|c|d|e/}).sort({"year":-1}).skip(X).limit(Y);
where X and Y are numbers.
The number of documents in my collection is:
208915369
Currently, this sort of query takes about 6 minutes to execute.
I have the following indexes:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"venue.raw" : 1
},
"name" : "venue.raw_1"
},
{
"v" : 2,
"key" : {
"venue.raw" : 1,
"title" : 1,
"year" : -1
},
"name" : "venue.raw_1_title_1_year_-1"
}
]
A standard document looks like this:
{ "_id" : ObjectId("5fc25fc091e3146fb10484af"), "id" : "1967181478", "title" : "Quality of Life of Swedish Women with Fibromyalgia Syndrome, Rheumatoid Arthritis or Systemic Lupus Erythematosus", "authors" : [ { "name" : "Carol S. Burckhardt", "id" : "2052326732" }, { "name" : "Birgitha Archenholtz", "id" : "2800742121" }, { "name" : "Kaisa Mannerkorpi", "id" : "240289002" }, { "name" : "Anders Bjelle", "id" : "2419758571" } ], "venue" : { "raw" : "Journal of Musculoskeletal Pain", "id" : "49327845" }, "year" : 1993, "n_citation" : 31, "page_start" : "199", "page_end" : "207", "doc_type" : "Journal", "publisher" : "Taylor & Francis", "volume" : "1", "issue" : "", "doi" : "10.1300/J094v01n03_20" }
Is there any way to make this query execute in a few seconds?
I have a document of following structure:
{
"Type" : "Request",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Processed",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Receieved",
"Cat" : "A",
"ID" : 10
}
{
"Type" : "Receieved",
"Cat" : "B",
"ID" : 11
}
{
"Type" : "Processed",
"Cat" : "C",
"ID" : 12
}
I want documents:
Those documents with Type: "Processed" and get its ID
And all the associated documents with the ID got from above (1st step).
I need the results to be like this:
{
"Type" : "Request"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Processed"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Receieved"
"Cat" : "A"
"ID" : 10
}
{
"Type" : "Processed"
"Cat" : "C"
"ID" : 12
}
Can someone help me on how to achieve this ? I used elemmatch under $match in aggregate - but its not working as expected.
You can try something like
db.collection.aggregate([
{$project : {
"ID":1,
"doc.Type" : "$Type",
"doc.Cat" : "$Cat",
"doc.ID" : "$ID"
}
}
{$group : {
_id : "$ID",
docs : {$push : doc}
}
},
{$match : {
"docs.Type":"Processed"
}
},
{$unwind : "$docs"},
{$project : {
_id : 0,
docs : 0,
"Type" : "$docs.Type",
"Cat" : "$docs.Cat",
"ID" : "$docs.ID"
}
}
])
Here is one of my document of my collection "entities", I can't figure out how to remove it.
{
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
},
"attrNames" : [
"TimeInstant",
"PING_status"
],
"attrs" : {
"PING_status" : {
"value" : "delivered but no respond",
"type" : "string",
"md" : [
{
"name" : "TimeInstant",
"type" : "ISO8601",
"value" : "2015-11-20T09:02:53.114688"
}
],
"creDate" : 1448010161,
"modDate" : 1448010172
},
"TimeInstant" : {
"value" : "2015-11-20T09:02:53.114834",
"type" : "ISO8601",
"creDate" : 1448010122,
"modDate" : 1448010172
}
},
"creDate" : 1448010122,
"modDate" : 1448010172
}
Any ideas? how can I remove the above document? Thanks in advance.
From doc:
db.collection.remove()
Removes documents from a collection.
1) By _ID: Since _ID is unique.
db.entities.remove( {"_id" :
{
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})
I would pass the _id to remove it.
db.entities.remove({
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})
remove document in mongodb
query = {"_id": <value of _id>}
db.entities.remove(query)
db.entities.remove(
"_id" : {
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath""id" : "sensors:StreetLight2"
}
)
you can also take any key-value pair from documents for remove
you can refer these links for better understanding
https://docs.mongodb.org/manual/tutorial/remove-documents/
https://docs.mongodb.org/manual/reference/method/db.collection.remove/
In mongo shell you should use .remove():
db.entities.remove(
{
"_id" :
{
"id" : "sensors:StreetLight2",
"type" : "sensors",
"servicePath" : "/egmmqttpath"
}
})
I have a collection of the following data:
{
"_id" : ObjectId("51f1fcc08188d3117c6da351"),
"cust_id" : "abc123",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 25,
"items" : [{
"sku" : "ggg",
"qty" : 7,
"price" : 2.5
}, {
"sku" : "ppp",
"qty" : 5,
"price" : 2.5
}]
}
I am using the query:
cmd { "aggregate" : "orders" , "pipeline" : [
{ "$unwind" : "$items"} ,
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}} ,
{ "$group" : { "price" : { "$first" : "$price"} , "items" : { "$push" : { "sku" : "$items.sku"}} , "_id" : { "items" : "$items"}}} ,
{ "$sort" : { "price" : -1}} ,
{ "$project" : { "_id" : 0 , "price" : 1 , "items" : 1}}
]}
Not able to understand what is going wrong
It's because you're doing $match after $unwind. $unwind generates a new stream of documents where items is no longer an array (see docs).
It emits each document as many times as there are items in it.
If you want to select documents with desired element in it and then process all of its documents, you should call $match first:
db.orders.aggregate(
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
{ "$unwind" : "$items"},
...
);
If you want to select items to be processed after $unwind, you shoul remove $elemMatch:
db.orders.aggregate(
{ "$unwind" : "$items"},
{ "$match" : { "items.qty" : { "$in" : [7]}}},
...
);
In first case you'll get two documents:
{
"price" : 25,
"items" : [
{"sku" : "ppp"}
]
},
{
"price" : 25,
"items" : [
{"sku" : "ggg"}
]
}
and in second case you'll get one:
{
"price" : 25,
"items" : [
{"sku" : "ggg"}
]
}
Update. After $unwind your documents will look like:
{
"_id" : ObjectId("51f1fcc08188d3117c6da351"),
"cust_id" : "abc123",
"ord_date" : ISODate("2012-10-03T18:30:00Z"),
"status" : "A",
"price" : 25,
"items" : {
"sku" : "ggg",
"qty" : 7,
"price" : 2.5
}
}
For small number of documents, unwind and match is fine. But large number of documents, it better to do - match ($elemMatch), unwind, and match again.
db.orders.aggregate(
{ "$match" : { "items" : { "$elemMatch" : { "qty" : { "$in" : [ 7]}}}}},
{ "$unwind" : "$items"},
{ "$match" : { "items.qty" : { "$in" : [7]}}}
...
...
);
The first match will filter only documents that match qty criteria. Among the selected documents, the second match will remove the subdocuments not matching the qty criteria.