I have a mongo collection that contains a field called "url", storing an url.
Some of those urls have an extra parameter that bothers me, "id=<>" where <> can have any size
Can i do this in a update operation or do i need to write a script that will iterate and replace?
db.find({{"url": /.&id=.*/ }}).update(???)
Your best bet is going to be to explore use of the "multi" parameter in conjunction with field update parameters, as described at these locations on the MongDB website.
http://docs.mongodb.org/manual/reference/operator/update-field/
http://docs.mongodb.org/manual/reference/method/db.collection.update/#multi-parameter
An example is provided here:
http://docs.mongodb.org/manual/reference/method/db.collection.update/#example-update-multi
The issue is that you won't be able to implement any sort of "capturing group" functionality that just gets rid of the "id" parameter for each document though. There is a ticket open on MongoDB's jira account though detailing this behavior (currently in unresolved state):
https://jira.mongodb.org/browse/SERVER-9159
Try this to find documents using this regEx and then do update accordingly.
db.find({
"url": /id=\<.+\>/
}, function(err, result) {
//your code
})
Related
I want to read last message node as shown in image below.
I am using below query to retrieve last message where suid and ids are known(as shown in img). but not working.
firebase.database().ref("Messages/"+suid).child(ids+"/chat").orderByKey().limitToLast(1);
How to retrieve last message from firebase realtime db and display it to my console? Thanks
Your existing code looks fine, so let's store that query in a variable first:
const query = firebase.database().ref("Messages/"+suid).child(ids+"/chat").orderByKey().limitToLast(1);
Now you can read the message(s) this query matches with either once() or get(). I'll use once(), since it's much older and hence you're more likely to find examples of it elsewhere:
query.once("value").then((snapshot) => {
snapshot.forEach((message) => {
console.log(message.val().message.msg);
});
})
Some things to note here:
Since a query may have multiple results, the snapshot contains a list of those results. Even if there's only a single result (like here), the snapshot is a list of one result. To loop over these results, we use snapshot.forEach().
Your msg is nested under message in each child, so we use message.val().message.msg to get at its value.
I have data model like this
Players-->root collection
Sports--->root collection
Players_Sports---root collection
I want get all the sports(Multiple sport) details or document player belongs.
For this I am using angularFireStore5
First, I am getting
Player details like this
this.db.collection('players').doc(id).get().toPromise()
Second, I am getting Player(user) linked PlayerSport
db.collection<any>('PlayerSports',ref => ref.where('playerId', '==', id) ).get().toPromise()
Third, I am trying to get Sports details based on ID'S,
db.collection<any>('sportsType', ref => ref.where('sportsType' 'in' [sportsIDs])).get().toPromise()
where SportIDs is arrary of ID that are linked in player_sports
First and Second steps works fine, but third steps is not giving any data or response
Could you please let me know where is the problem,
is it in Data model or code? my guess is that data model is not correct. Please guide me on this.
I would suggest getting the data from firebase and storing it inside a list so the app can access it later.
void getDataF(){
databaseReference
.collection("TableName")
.getDocuments()
.then((QuerySnapshot snapshot) {
snapshot.documents.forEach((f) {
iDFacList.add(f.documentID);
dbFacList.add(f.data["FieldName"]);
});
});
}
There is no sportsType field in the sportsType document as far as I can see.
If you're trying to find documents based on their SportsId field, you'll want ref.where('SportsId'....
Update
It seems that you're trying to find a document by its ID, which you can do with:
ref.doc(sportsIDs)
If you want to get multiple documents, or get a single document as a collection, you can use:
ref.where(firebase.firestore.FieldPath.documentId() 'in' [sportsIDs])
I have been building my Meteor React application but ran into a problem now. I would like to delete all the "fake" generated data I added. But it's not working.
I have tried several things, from server side deleting (via the console) and via a method. But none of these have worked so far.
So my question: How can you delete all data in a collection that matches a query like this one:
comments.remove({ adminSpark : { $regex: 'false', $options: 'i' }});
--> Not sure if this method is correct.
I am using SimpleSchema + ValidatedMethod.
The complete method looks like this at the moment:
export const emptyDatabase = new ValidatedMethod({
name: 'AllComments.remove',
validate: new SimpleSchema({
event: { type: Boolean }
}).validator(),
run({ event }) {
comments.remove({ adminSpark : { $regex: 'false', $options: 'i' }});
},
});
So what I want to do is delete all the comments in the collection that match adminSpark: false.
The validity of your selector depends on wether your code is trusted or not. Untrusted code can only remove elements using their _id as a selector. If you are not sure wether your code is trusted or not, I'd suggest :
Collection.find({/*query here*/}).map(function(doc){
Collection.remove(doc._id);
})
Also this should be performed in a space were you are both subscribed to the elements you want to remove and where you have permissions to do so.
Documentation:
Trusted code can use an arbitrary Mongo selector to find the documents to remove, and can remove more than one document at once by passing a selector that matches multiple documents. It bypasses any access control rules set up by allow and deny. The number of removed documents will be returned from remove if you don’t pass a callback.
As a safety measure, if selector is omitted (or is undefined), no documents will be removed. Set selector to {} if you really want to remove all documents from your collection.
Untrusted code can only remove a single document at a time, specified by its _id. The document is removed only after checking any applicable allow and deny rules. The number of removed documents will be returned to the callback.
On the server you should be able to simply do:
comments.remove({ adminSpark : 'false' });
If all your false values are lower case - this is an exact match.
Pray tell, why would one store false as a string instead of a boolean?
I've looked through a bunch of other SO posts and have found different ways to do this, so I'm wondering which is most preferred. I'm teaching this to students, so I want to give them best practices.
If I have the following BlogPost object (Simplified):
var BlogPostSchema = new mongoose.Schema({
body: String,
comments: [String]
});
and I want to add a new comment to the array of comments for this blog, I can think of at least 3 main ways to accomplish this:
1) Push the comment to the blog object in Angular and submit a PUT request to the /blogs/:blogID endpoint, updating the whole blog object with the new comment included.
2) Submit a POST request to a /blogs/:blogID/comments endpoint where the request body is just the new comment, find the blog, push the comment to the array in vanilla js, and save it:
BlogPost.findById(req.params.blogID, function(err, blogPost) {
blogPost.comments.push(req.body);
blogPost.save(function(err) {
if (err) return res.status(500).send(err);
res.send(blogPost);
});
});
OR
3) Submit the POST to a /blogs/:blogID/comments endpoint with the request body of the new comment, then use MongoDB's $push or $addToSet to add the commend to the array of comments:
BlogPost.findByIdAndUpdate(
req.params.blogID,
{$push: {comments: req.body}},
{safe: true, new: true},
function(err, blogPost) {
if (err) return res.status(500).send(err);
res.send(blogPost);
});
});
I did find this stackoverflow post where the answerer talks about option 2 vs. option 3 and basically says to use option 2 whenever you can, which does seem simpler to me. (And I usually try to avoid methods that stop me from being able to use hooks and other mongoose goodies.)
What do you think? Any advice?
From application point of view, point 3 is better. The reason I think are.
The query itself specifies what we are trying to achieve. it's
easily readable.
save function is a wild card, so we don't know what it's going to change.
if you fetch the document and manipulate it and then call save it, there is outside but real chance that you might mess up some
other field of the document in process of manipulation
unintentionally, not the case with point 3.
In case of addToSet,basically the previous point is more visible.
Think about the concurrency, if multiple calls comes with different comment for same blog and you are trying option 2, there
is a chance that you might override the changes which were done in
between you fetched the document and when you are saving it. Option
3 is better in that sense.
Performance wise they both do the same thing, so there might not be much or any visible difference. But option 3 is bit safer and cleaner.
In my database, I have a field called 'fruits' which is a simple array. When inserting elements in this array, I use $addToSet to only insert elements that do not exist already in this array.
I want to know whether or not the element I insert really modified this field. However, the docModified parameter in the callback always returns 1 even when I try to add an element that already exists.
model.update (
{ username: username }, // find the document
{ $addToSet : { fruits: "apple" } }, // add "apple" to fruits field
function (err, docModified) {
console.log(docModified);
// !PROBLEM: this will print "1" no matter what
}
);
Does anyone know why? Thanks a lot! (btw I'm using Mongoose)
The current method implementations in mongoose use the legacy write concern API to determine the count of modified documents. As you note, even if there is no actual change to the content such as an $addToSet operation that does not add a new member to the set, the modified count will be returned.
As long as your MongoDB server version is recent enough ( needs to be MongoDB 2.6 or greater ) and your mongoose version is recent enough an bundles a recent mongodb driver, then you can get the correct numbers from the Bulk Operations API responses.
To do this with mongoose you call the .collection accessor on the model, which returns a native driver collection object:
var bulk = Model.collection.initializeOrderedBulkOp();
bulk.find({ username: username })
.updateOne({ $addToSet : { fruits: "apple" } });
bulk.execute(function(err,result) {
if (err) throw err;
console.log( JSON.stringify( result, undefined, 4 ) );
})
The "result" that is returned is an object conforming to the BulkWriteResult() specification, which more or less will look like this:
{
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 2,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 1,
"upserted" : [ ]
}
But specifically, where you use $addToSet and the member already exists, the response will contain "nMatched": 1 and "nModified": 0, which is the result you want to see, confirming that nothing was in fact added to the set.
In the MongoDB 2.6 shell, all of the update and insert methods try to use this API where it is available and only fallback to the legacy implementation when connecting to an older server. So If you did this in a modern shell with a modern server you would see the same results.
Hopefully mongoose itself will be altered to also use these methods where available and provide access to the same response. It seems to be the way of the future, but the codebase is yet to catch up and utilize this.
Note: The one thing to be careful of when using any of the native driver methods after accessing the collection object is to make sure that mongoose has an active connection to the database at the time this is called. Mongoose hides this by queuing up any request until a connection is actually established.
So if you are going straight to the collection object methods, then you might want to make sure you are waiting for the "open" event on the connection somewhere before that code executes.
"number affected is the number of docs updated, even if the new values are identical. this comes straight from mongo." I got this from this forum post: https://github.com/LearnBoost/mongoose/issues/867
This means you'll have to come up with a different way to determine if the element was missing from the array before you update. I would recommend pull all the documents and iterating through them before the update. Obviously it's not ideal, but i don't think there's any other way to do it.
Hope this helps.