MongoDB C# Remove doesn't work - mongodb

i have this code for removing an item froma a mongofb collation
private MongoCollection<T> GetCollection()
{
connectionString = "mongodb://localhost/?safe=true";
server = MongoServer.Create(connectionString);
database = server.GetDatabase("CSCatalog");
return database.GetCollection<T>("myCollectionName");
}
public bool Delete(T entity)
{
var id = typeof(T).GetProperty("Id").GetValue(entity,null).ToString();
var query = Query.EQ("_id",id);
var finded = GetCollection().Find(query); // return null
var result= GetCollection().Remove(query, MongoDB.Driver.RemoveFlags.Single); // no errors, but don't remove
return esito.Ok; //return true but donn't remove.
}
the GetCollection() method retrive the right collection, i have tested it width debug.
In the collection there is the item that i want remove, it have the same id that i have retrived in first line.
the entity have some fields and a Objectid filed called "Id"

the type of _id you created is ObjectId class and you are trying to equate with string so its not able to remove. use
var queryId = new ObjectId(id);

Your finded variable should not be null if the .find() has returned something from your database. That it is null means that you have not found anything, and therefore nothing is to be removed.
What it looks like is happening here is that you are querying on _id for the ObjectId, while you are storing that ObjectId in the database as Id.

Related

MongoDb C# Driver 2.0 add item to nested array

I have a Profiles document collection with array of the following documents :
public class Profile2MailList
{
[BsonElement(elementName: "listId")]
[BsonRequired]
public int MailListId;
[BsonElement(elementName: "status")]
[BsonRequired]
public int Status;
[BsonElement(elementName: "subscriptionDate")]
[BsonRequired]
public DateTime SubscriptionDate;
}
in each Profile.
I need to add to the Profile2MailList array a new Profile2MailList document in each Profile based on Profile2MailList which already contains in a certain Profile. So i need to
Take needed profiles from Profiles collection
Update
Profile2Maillist array in each Profile
Run update command
How can i perform that action via C# 2.0 MongoDb Driver. I have MongoDb v 3.0.2.
I try to make it by the following way :
List<Profile> listProfiles = new List<Profile>();
foreach (Profile item in profiles)
{
item.MailLists.ToList().Add(new Profile2MailList(maillistId, item.MailLists.FirstOrDefault().Status));
var t = item;
listProfiles.Add(t);
}
dbCollection.UpdateManyAsync(listProfiles)
The method "UpdateManyAsync" only works if you want to perform one type of update, which doesn't seem to be your case. What you want to do is perform a Bulk-Update instead. Building on your example, you would want to do something like:
var bulk = new List<WriteModel<Profile>>();
foreach (Profile item in profiles)
{
var newProfile = new Profile2MailList(maillistId, item.MailLists.FirstOrDefault().Status);
var filter = Builders<Profile>.Filter.Eq(g => g.Id, item.Id);
var update = Builders<Profile>.Update.AddToSet(item.MailLists, newProfile);
var updatemodel = new UpdateOneModel<Profile>(filter, update);
bulk.Add(updatemodel);
}
await profileCollection.BulkWriteAsync(bulk);
The AddToSet operator adds a value to an array unless the value is already present.

Programmatically updating fields in Mongo and Meteor

I have a collection that I'd like to update. The field is given programmatically, so I'd like to do something like this:
var update_string = 'coordinates.lat';
var update = function(value, id, update_string) {
Collection.update({_id:id}, {$set:{update_string:value}})
}
That however does not work and just sets "update_string" to have value {{value}} in the object with _id {{id}} in the Collection. I also tried doing var update_string = "'coordinates.lat'"; to no avail.
How do I accomplish this? Thanks.
You need to set the key in your update $set parameter correctly:
var update = function(value, id, update_string) {
var update_query = {};
update_query[update_string] = value
Collection.update({_id:id}, {$set:update_query})
}
Basically without the modification above, If you used {update_string:value} you would be setting the value of update_string, not coordinates.lat.

using findAndModify in mongodb using grails gorm

I need to use findAndModify in my application with grails and mongoDB.
I used this code :
public static String getNextId(DB db, String seq_name) {
String sequence_collection = "seq"; // the name of the sequence collection
String sequence_field = "seq"; // the name of the field which holds the sequence
DBCollection seq = db.getCollection(sequence_collection); // get the collection (this will create it if needed)
// this object represents your "query", its analogous to a WHERE clause in SQL
DBObject query = new BasicDBObject();
query.put("_id", seq_name); // where _id = the input sequence name
// this object represents the "update" or the SET blah=blah in SQL
DBObject change = new BasicDBObject(sequence_field, 1);
DBObject update = new BasicDBObject("$inc", change); // the $inc here is a mongodb command for increment
// Atomically updates the sequence field and returns the value for you
DBObject res = seq.findAndModify(query, new BasicDBObject(), new BasicDBObject(), false, update, true, true);
return res.get(sequence_field).toString();
}
and it work successful. But now I want use findAndModify without native mongodb object, and with using GORM.
Is there any solution for this work?
There is not way to accomplish this without native API, you can however write your code a bit more compact like this:
def collection = Seq.collection
collection.findAndModify([_id: seq_name ], [ "\$inc": [seq:1] ])
Config your DataSource.groovy with db configurations.
Then define a Domain class:
Class Seq{
int seq
}
And use dynamic finder in a sevice:
Class SeqService {
String findAndModify(String seq_name) {
def seqInstance = Seq.get(seq_name)
if(seqInstance){
seqInstance.seq ++
seqInstance.save()
return seqInstance.seq.toString()
}
return '' //instance not found
}
}
Then make a call when you need that action:
def seqService
def id
.......
def result = seqService.findAndModify(id)
....

MongoDb: how to return distinct field in select (find) with C# official driver

I need to select User Name from the collection of Users. I do it in a such way:
MongoCollection<Enums> coll = Db.GetCollection<Enums>("Users");
var query = Query.EQ("_id", id);
var res = coll.FindOne(query);
var name = res.Name;
var url = res.UserUrl; //or some more fields, not just Name
Assuming that User document can contain a lot of data, and there is no need to transfer the whole user document, how to select only a few distinct fields, using official C# driver?
You'll have to use a function that returns a MongoCursor.
In the MongoCursor you can specify the fields you want to return.
var result = Db.GetCollection<Enums>("Users").FindAll();
result.Fields = Fields.Include(new [] {"Name"});;
foreach (var user in result)
{
Console.WriteLine(user.Name);
}

How do I get the date a MongoDB collection was created using MongoDB C# driver?

I need to iterate through all of the collections in my MongoDB database and get the time when each of the collections was created (I understand that I could get the timestamp of each object in the collection, but I would rather not go that route if a simpler/faster method exists).
This should give you an idea of what I'm trying to do:
MongoDatabase _database;
// code elided
var result = _database.GetAllCollectionNames().Select(collectionName =>
{
_database.GetCollection( collectionName ) //.{GetCreatedDate())
});
As far as I know, MongoDB doesn't keep track of collection creation dates. However, it's really easy to do this yourself. Add a simple method, something like this, and use it whenever you create a new collection:
public static void CreateCollectionWithMetadata(string collectionName)
{
var result = _db.CreateCollection(collectionName);
if (result.Ok)
{
var collectionMetadata = _db.GetCollection("collectionMetadata");
collectionMetadata.Insert(new { Id = collectionName, Created = DateTime.Now });
}
}
Then whenever you need the information just query the collectionMetadata collection. Or, if you want to use an extension method like in your example, do something like this:
public static DateTime GetCreatedDate(this MongoCollection collection)
{
var collectionMetadata = _db.GetCollection("collectionMetadata");
var metadata = collectionMetadata.FindOneById(collection.Name);
var created = metadata["Created"].AsDateTime;
return created;
}
The "creation date" is not part of the collection's metadata. A collection does not "know" when it was created. Some indexes have an ObjectId() which implies a timestamp, but this is not consistent and not reliable.
Therefore, I don't believe this can be done.
Like Mr. Gates VP say, there is no way using the metadata... but you can get the oldest document in the collection and get it from the _id.
Moreover, you can insert an "empty" document in the collection for that purpose without recurring to maintain another collection.
And it's very easy get the oldest document:
old = db.collection.find({}, {_id}).sort({_id: 1}).limit(1)
dat = old._id.getTimestamp()
By default, all collection has an index over _id field, making the find efficient.
(I using MongoDb 3.6)
Seems like it's some necroposting but anyway: I tried to find an answer and got it:
Checked it in Mongo shell, don't know how to use in C#:
// db.payload_metadata.find().limit(1)
ObjectId("60379be2bec7a3c17e6b662b").getTimestamp()
ISODate("2021-02-25T12:45:22Z")