I have a document collection like this:
{
"_id" : ObjectId("4fb21439f31dfd122ce39c4a"),
"Name" : "Freelander 2",
"Manufacture" : "Landrover"
}
I am using the C# driver, and want to check whether the "Name" field exists; if it does not, I need to update it from the code. Can someone help on this? Please share sample code because I am a newbie to mongoDB.
You can use the exists operator:
db.myCollection.find( { Name: { $exists: true } } );
Using the C# driver, the equivalent would be something like this:
IMongoQuery query = Query.Exists("Name", true)
var results = myCollection.Find(query);
To set a value if it doesn't exist, you can use an Update statement like this:
IMongoQuery query = Query.Exists("name", true);
IMongoUpdate update = Update.Set("Name", "newvalue");
myCollection.Update(query, update);
I'm assuming you want to update all documents that don't have a Name field to the same value. You can do that in the mongo shell like this:
> db.test.update({Name:{$exists:false}}, {$set:{Name:"xyz"}}, false, true)
You can do the same thing in C# like this:
var query = Query.Exists("Name", false);
var update = Update.Set("Name", "xyz");
collection.Update(query, update, UpdateFlags.Multi);
Related
I have a MongoDB Document as follows
{
"_id" : ObjectId("5a55775cbd12982cc063c71a"),
"ShipmentNumber" : "00004000000048652254",
"Cartons" : [
{
"_id" : ObjectId("5a5575bcbd12982cc063b718"),
"CartonNumber" : "0076013926580S",
"Skus" : [
{
"_id" : ObjectId("5a5575bcbd12982cc063b719"),
"SkuNumber" : "06577647",
"ShippedQuantity" : 12,
},
{
"_id" : ObjectId("5a5575bcbd12982cc063b519"),
"SkuNumber" : "06577657",
"ShippedQuantity" : 15,
}
],
"IsScanned" : false,
},
}
How can I update the "ShippedQuantity" for a particular Sku element based on its "_id" in C# code ?
I tried something like below. But it is not working.
Getting error message like
cannot use the part (Cartons of Cartons.$[].Skus.$.ShippedQuantity) to
traverse the element
var filter = Builders<BsonDocument>.Filter.Eq("Cartons.Skus._id", new ObjectId("5a5575bcbd12982cc063b519"));
var update = Builders<BsonDocument>.Update.Set("Cartons.$[].Skus.$.ShippedQuantity", 50)
I am facing difficulties when I try to update multi level documents.
(In this case I have a list of Cartons and each carton will have its own list of skus and I need to update a specific sku's element)
Please provide a solution or alternative approach to update this inner level (more than 2 levels) documents in MongoDB using C#.
I updated my MongoDB server to the latest 3.6.1. But that is also not helping.
Thanks for your help.
First, you need to run this command in your MongoDB to apply the new features of version 3.6.1 db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )
Here is the code you need for that update:
var filter = Builders<YOUR_CLASS>.Filter.Eq("_id", new ObjectId("5a55775cbd12982cc063c71a"));
var update = Builders<YOUR_CLASS>.Update.Set("Cartons.$[i].Skus.$[j].ShippedQuantity", 50);
var arrayFilters = new List<ArrayFilterDefinition>
{
new BsonDocumentArrayFilterDefinition<Setup>(new BsonDocument("i._id", new ObjectId("5a5575bcbd12982cc063b718"))),
new BsonDocumentArrayFilterDefinition<Setup>(new BsonDocument("j._ID", new ObjectId("5a5575bcbd12982cc063b719")))
};
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
var (updated, errorMessage) = await UpdateOneAsync(filter, update, updateOptions);
Additionally, you can run set these settings in your MongoDB to look at your final queries and run them manually in RoboMongo or Studio 3T to debug them:
db.setProfilingLevel(2) -> to view query logs under C:\data\log\mongod.log
db.setLogLevel(5) -> to view query logs under C:\data\log\mongod.log
look for the "UPDATE" query in the log file. After that, you can reset the log setting back to 0
db.setProfilingLevel(0)
db.setLogLevel(0)
I've had the same problem and asked the same question Here
Have a look at it.
I am trying to update an existing Mongo record, but am getting an "Additional information: Element name 'ID' is not valid'." error
I have a a BsonDocument "document" containing data that I retrieve from another source that looks like this:
{ "ID" : "ABCecdcf9851efbf0ef66953", ListingKey : "234534345345", "Created" : ISODate("2017-08-04T00:31:23.357Z"), "Modified" : ISODate("2017-08-04T00:31:23.358Z"), "Field1" : 1, "Field2" : "0.09", "Field3" : "1.10", "Field4" : "1", "Field5" : "1" }
Here is the C# code that I have written:
var collection = db.GetCollection<BsonDocument>("MyCollection");
//Hard coded for testing
var filter = Builders<BsonDocument>.Filter.Eq("ListingKey", "234534345345");
collection.UpdateOne(filter, document);
Is this related to the BsonDocument that I am trying to use to update? I found this documentation, which causes me to think that this is the cause. If so, is there a way to do an update with the format I have been provided?
https://docs.mongodb.com/getting-started/csharp/update/
I had a process working where it would delete the document and then add a new document, but for efficiency's sake I need this to update. Ideally it will only update the fields that are present in the BsonDocument and keep the existing fields in the Mongo document as is.
My problem was because I did not have the correct value when trying to update. My code works with this:
var collection = db.GetCollection<BsonDocument>("MyCollection");
//Hard coded for testing
var filter = Builders<BsonDocument>.Filter.Eq("ListingKey", "234534345345");
var update = Builders<BsonDocument>.Update.Set("Created", DateTime.UtcNow);
foreach (BsonElement item in document)
{
update = update.Set(item.Name, item.Value);
}
var result = collection.UpdateOne(filter, update);
I had to convert my string into an update BsonDocument.
I have following mongo shell query:
{'field':'FieldOne','value':'FieldOne','category':'categoryOne'} , { 'Color' : { '$elemMatch' : { 'Value' : 'Green' } }}
Is there any way to execute same query using C# mongo driver?. I have tried using below C# code, but only the first one is getting executed:
BsonDocument query = BsonDocument.Parse("{'field':'Overall','value':'Overall','category':'LoggedIncidents'} , { 'Priority' : { '$elemMatch' : { 'Value' : 'P1' } }}");
QueryDocument queryDoc = new QueryDocument(query);
var result = collection.Find(queryDoc).ToListAsync().Result;
The first item ({'field':'FieldOne','value':'FieldOne','category':'categoryOne'}) is being executed but not the second one ({ 'Color' : { '$elemMatch' : { 'Value' : 'Green' } }}).
You are using it in find command if i'm not wrong.
the first "{}" is what the filter condition for find is. next set of parameters are essentially to show/hide the fields you need.
so if you want to filter by value of array "green" you can do this.
db.objects.find({"color":{$elemMatch:{value:"green"}}})
should give you the results you are looking for. but if you want to specifically show/hide fields, you can do
db.objects.find({"color":{$elemMatch:{value:"green"}}},{"field":1})
is this what you want to attain?
I have many complex queries that I sometimes wish to check directly against Mongo for debugging \ explaining() purposes.
With the newer 2.0+ c# driver, i'm not sure how to do this. With the previous version there was a thing called IMongoQuery and This worked.
A simple example:
FilterDefinition<LalalaEvent> filter = Builders<LalalaEvent>.Filter
.Where(e => ids.Contains(e.Id) && e.Deleted != true );
I was trying to solve the same problem today. Here is what I found.
public static class MongoExtensions
{
public static BsonDocument RenderToBsonDocument<T>(this FilterDefinition<T> filter)
{
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<T>();
return filter.Render(documentSerializer, serializerRegistry);
}
}
I didn't have access to a collection when I was calling it, so I couldn't use the above solutions.
This allows you to do
var json = filter.RenderToBsonDocument().ToJson();
If you're using the latest version of the driver, which is 2.0.1 you can easily put that filter in a Find operation, get back an IFindFluent and print its ToString:
var filter = Builders<LalalaEvent>.Filter.Where(e => ids.Contains(e.Id) && e.Deleted != true);
var findFluent = collection.Find(filter);
Console.WriteLine(findFluent);
For example for me this prints:
find({ "_id" : { "$in" : [1, 2, 3] }, "Deleted" : { "$ne" : true } })
You are able to perform that using the collection's properties:
var result = filter.Render(collection.DocumentSerializer,
collection.Settings.SerializerRegistry).ToString();
I have many complex queries that I sometimes wish to check directly against Mongo for debugging \ explaining() purposes.
With the newer 2.0+ c# driver, i'm not sure how to do this. With the previous version there was a thing called IMongoQuery and This worked.
A simple example:
FilterDefinition<LalalaEvent> filter = Builders<LalalaEvent>.Filter
.Where(e => ids.Contains(e.Id) && e.Deleted != true );
I was trying to solve the same problem today. Here is what I found.
public static class MongoExtensions
{
public static BsonDocument RenderToBsonDocument<T>(this FilterDefinition<T> filter)
{
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<T>();
return filter.Render(documentSerializer, serializerRegistry);
}
}
I didn't have access to a collection when I was calling it, so I couldn't use the above solutions.
This allows you to do
var json = filter.RenderToBsonDocument().ToJson();
If you're using the latest version of the driver, which is 2.0.1 you can easily put that filter in a Find operation, get back an IFindFluent and print its ToString:
var filter = Builders<LalalaEvent>.Filter.Where(e => ids.Contains(e.Id) && e.Deleted != true);
var findFluent = collection.Find(filter);
Console.WriteLine(findFluent);
For example for me this prints:
find({ "_id" : { "$in" : [1, 2, 3] }, "Deleted" : { "$ne" : true } })
You are able to perform that using the collection's properties:
var result = filter.Render(collection.DocumentSerializer,
collection.Settings.SerializerRegistry).ToString();