How do you delete a Json object by id in node Mongodb? - node.js

i have a Mongodb collection named "EVENTS" and in the collection i have an object of array which looks like this:
{
"Events":[
{
"_id":"53ae59883d0e63aa77f7b5b2",
"Title":"Title Blank",
"Desc":"Description Blank",
"Date":"2014-06-04 00:30",
"Link":"http://googleparty.com",
"Event":"Victoria Centre",
"dateCreated":"28/6/2014 06:58"
},
{
"_id":"53ae59883d0e63aa77f7b5b3",
"Title":"Hello World",
"Desc":"hello",
"Date":"2014-06-04 00:30",
"Link":"http://linkedinparty.com",
"Event":"social",
"dateCreated":"30/2/2014 11:10"
}
]
}
how would i delete an object by id in node.js so " delete(53ae59883d0e63aa77f7b5b2)" will yield this:
{
"Events":[
{
"_id":"53ae59883d0e63aa77f7b5b3",
"Title":"Hello World",
"Desc":"hello",
"Date":"2014-06-04 00:30",
"Link":"http://linkedinparty.com",
"Event":"social",
"dateCreated":"30/2/2014 11:10"
}
]
}
Regards

If all you really want to do is "empty" the array then you just need to use the $set operator with an .update() and "set" the array as an empty one:
db.collection.update({},{ "$set": { "Events": [] } },{ "mutli": true})
So the .update() operation takes a "query" to select the documents in your collection, a blank query as shown selects everything. The "update" section contains the $set operation that just replaces the current "Events" field with an empty array.
The "multi" option there makes sure this is applied to every document that matches. The default is false and will only update the first document that matches.
For more specific operations removing selected array elements, look at the $pull operator. Your edit shows now that this is what you want to do:
db.collection.update(
{ "Events._id": ObjectId("53ae59883d0e63aa77f7b5b2") },
{ "$pull": { "Events": { "_id": ObjectId("53ae59883d0e63aa77f7b5b2") } } }
)
But your inclusion of arrays with _id fields seems to indicate that you are using mongoose, so the ObjectId values are cast automatically:
Model.update(
{ "Events._id": "53ae59883d0e63aa77f7b5b2" },
{ "$pull": { "Events": { "_id": "53ae59883d0e63aa77f7b5b2" } } },
function(err,numAffected) {
}
);

Related

Mongo indexing on nested object

My mongodb collection's structure looke like this,
{
paymentTree: {
t1: { from: "id-123", to: "id-2334", },
t2: { from: "id-1443", to: "id-567", },
t3: { from: "id-76567", to: "id-2334", },
tn: { from: "id-12n", to: "id-233n", }
}
How can index field 'to' in paymentTree?
Currently it is not possible to create index in dynamic object key,
If you want to achieve anyway then I would suggest if you could transform your schema structure to The Attribute Pattern,
change paymentTree object type to array type,
change object to array in key-value pairs, k for tree's dynamic key and v for { from, to } object,
{
paymentTree: [
{
"k": "t1",
"v": { "from": "id-123", "to": "id-2334" }
},
{
"k": "t2",
"v": { "from": "id-1443", "to": "id-567" }
},
{
"k": "t3",
"v": { "from": "id-76567", "to": "id-2334" }
},
{
"k": "tn",
"v": { "from": "id-12n", "to": "id-233n" }
}
]
}
Benefits of this structure:
Create Multikey Single Field Index on to:
You can create multikey indexes on array fields that contain nested objects,
db.collection.createIndex({ "paymentTree.v.to": 1 });
Create Multikey Compound Index on k and to:
db.collection.createIndex({ "paymentTree.k": 1, "paymentTree.v.to": 1 });
Push object to array:
You can insert object to paymentTree array using $push in update methods (updateOne and updateMany).
Pull object from array:
You can remove specific object on the base of k from paymentTree array using $pull in update methods (updateOne and updateMany).
Match conditions:
You can easily match conditions using conditional operators,
Ex.1:
{ "paymentTree.k": "t1" }
Ex.2:
{ "paymentTree.v.to": "id-2334" } // or { "paymentTree.v.from": "id-123" }
Ex.3:
{
"paymentTree": {
"$elemMatch": {
"k": "t1",
"v.to": "id-2334" // or "v.from": "id-123"
}
}
}
How can i easily select like paymentTree.t1, ..:
In Query:
There is a operator called $arrayToObject, you can convert paymentTree array to object in projection stages ($project, $addFields, $set) see Playground,
The find() and findOne() projection can accept aggregation expressions and syntax from MongoDB v4.4 projection consistent with aggregation’s $project stage,
Outside Query:
You need to convert peymentTree array to object format in your client side language (go, node.js, etc.).
this works for me
_, err = db.Comments.Indexes().CreateOne(db.Ctx, mongo.IndexModel{Keys: bson.M{"t1.to": 1}})
if err != nil {
panic(err)
}

Loop inside mongo query

I'm new to MongoDB. And in my collection, I have an array of data. And at the user end, I also have an array. I want to match the user end array with the collection array if any of the elements match with the collection array data, the should be considered as a result. Below is my collection :
{
"_id": {
"$oid": "5f5b2f728cae440be88437f0"
},
"course": ["5f378f6aaf169e22d01d32d4", "5f2ba101f012a62ed011f3ae"],
"access": 1,
"status": 1,
"title": "Simplification",
"createdAt": {
"$date": "2020-09-11T08:04:02.896Z"
},
"updatedAt": {
"$date": "2020-09-11T08:04:02.896Z"
},
"__v": 0
}
And let's suppose I have an array on the user end like:-
var my_courses=["5f378f6aaf169e22d01d32d4","5f6449e726f13210b026635d"];
I want to match this array with the collections course column array. Either the array elements match with the collection or the access should be 0.
Here is my mongo query:-
const videos=await Vimeo_Videos
.find({status: 1},'$and':[ { '$and':[ { course: { '$elemMatch': {'$eq':'5f378f6aaf169e22d01d32d4' } } } ],'$or': [ { access: 0 } ] } ] }).limit(4)
How can I run a loop inside the query to match all array elements with a collection array? Please suggest me solution how can I do that.
If you are sure about the elements in the array, you could write like this-
{ course: {$all:['5f378f6aaf169e22d01d32d4','5f6449e726f13210b026635d']} }
So, your code would be-
const videos=await Vimeo_Videos.find({ course: {$all: '5f378f6aaf169e22d01d32d4','5f6449e726f13210b026635d']} })
Not sure if this what you are looking for. Hope it helps some way!

How to match and join results between two resolvers in one graphql query?

I have two resolver.
The one is Company resolve that return the company details like id, name and list of documents ids, like this example:
{
"data": {
"companyOne": {
"name": "twitter",
"documents": [
"5c6c0213f0fa854bd7d4a38c",
"5c6c02948e0001a16529a1a1",
"5c6c02ee7e76c12075850119",
"5c6ef2ddd16e19889ffaffd0",
"5c72fb723ebf7b2881679ced",
"5c753d1c2e080fa4a2f86c87",
...
]
}
}
}
And the another resolver gets me all the details of documents like this example:
{
"data": {
"documentsMany": [{
"name": "doc1",
"_id": 5c6c0213f0fa854bd7d4a38c,
}, {
"name": "doc2",
"_id": 5c6c02948e0001a16529a1a1,
},
...
]
}
}
How to match every data.companyOne.documents[id] to data.documentsMany[..]._id? in the query level? is it possible to do this graphql?
The expect results should be when I run the companyOne query (without change the code - just in the query level) it's should return with documents as object instead of array of string ids.
maybe something like?
query {
companyOne {
name,
documents on documentsMany where _id is ___???
}
}

How do I query for the value of a key in an object? [duplicate]

So I'm attempting to find all records who have a field set and isn't null.
I try using $exists, however according to the MongoDB documentation, this query will return fields who equal null.
$exists does match documents that contain the field that stores the null value.
So I'm now assuming I'll have to do something like this:
db.collection.find({ "fieldToCheck" : { $exists : true, $not : null } })
Whenever I try this however, I get the error [invalid use of $not] Anyone have an idea of how to query for this?
Use $ne (for "not equal")
db.collection.find({ "fieldToCheck": { $ne: null } })
Suppose we have a collection like below:
{
"_id":"1234"
"open":"Yes"
"things":{
"paper":1234
"bottle":"Available"
"bottle_count":40
}
}
We want to know if the bottle field is present or not?
Ans:
db.products.find({"things.bottle":{"$exists":true}})
i find that this works for me
db.getCollection('collectionName').findOne({"fieldName" : {$ne: null}})
This comment is written in 2021 and applies for MongoDB 5.X and earlier versions.
If you value query performance never use $exists (or use it only when you have a sparse index over the field that is queried. the sparse index should match the criteria of the query, meaning, if searching for $exists:true, the sparse index should be over field:{$exist:true} , if you are querying where $exists:true the sparse index should be over field:{$exist:false}
Instead use :
db.collection.find({ "fieldToCheck": { $ne: null } })
or
db.collection.find({ "fieldToCheck": { $eq: null } })
this will require that you include the fieldToCheck in every document of the collection, however - the performance will be vastly improved.
db.<COLLECTION NAME>.find({ "<FIELD NAME>": { $exists: true, $ne: null } })
In my case, i added new field isDeleted : true to only fields that are deleted.
So for all other records there was no isDeleted field, so i wanted to get all the fields that isDeleted either does not exist or false. So query is
.find({ isDeleted: { $ne: true } });
I Tried to convert it into boolean condition , where if document with
table name already exist , then it will append in the same document ,
otherwise it will create one .
table_name is the variable using which i am trying to find the document
query = { table_name : {"$exists": "True"}}
result = collection.find(query)
flag = 0
for doc in result:
collection.update_one({}, { "$push" : { table_name : {'name':'hello'} } } )
flag = 1
if (flag == 0):
collection.insert_one({ table_name : {'roll no' : '20'}})
aggregate example
https://mongoplayground.net/p/edbKil4Zvwc
db.collection.aggregate([
{
"$match": {
"finishedAt": {
"$exists": true
}
}
},
{
"$unwind": "$tags"
},
{
"$match": {
"$or": [
{
"tags.name": "Singapore"
},
{
"tags.name": "ABC"
}
]
}
},
{
"$group": {
"_id": null,
"count": {
"$sum": 1
}
}
}
])

Aggregate using $size without exception if array doesn't exist [duplicate]

Trying to create a MongoDB data source with icCube. The idea is to return the size of an array as a new field. Something like :
$project:
{
"people": 1,
"Count myFieldArray" : {$size : "$myFieldArray" }
}
But I'm getting for some records the following error :
The argument to $size must be an Array, but was of type: EOO
Is there a way that size is 0 if the field is empty or not an array (getting rid of the error) ?
You can use the $ifNull operator here. It seems the field is either not an array or not present by the given error:
{ "$project": {
"people": 1,
"Count": {
"$size": { "$ifNull": [ "$myFieldArray", [] ] }
}
}}
Also you might want to check for the $type in your $match in case these do exist but are not an array.
From MongoDB 3.2 and newer, you can use $isArray to check if your field is an array along with the $cond operator to return the field on evaluating with $isArray:
{ "$project": {
"people": 1,
"myFieldArrayCount": {
"$size": {
"$cond": [
{ "$isArray": "$myFieldArray" },
"$myFieldArray",
[]
]
}
}
}}
Alternative solution would be to eliminate the documents with nulls using
$match: {myFieldArray: { $elemMatch: { $exists: true } }}
Also, document fields which are used as arguments to $size by '$' reference (here: "$myFieldArray") must also be the part of projections.
$project:
{
"people": 1,
"myFieldArray":1,
"Count myFieldArray" : {$size : "$myFieldArray" }
}

Resources