Check Existence of Column in MongoDb - c#

I have asked to create a function that can update a MongoDb collection by passing it's column names and corresponding values.The function that I wrote(in test phase now) will accept column names, values, collection name etc.before updating I want to check whether the given collection exists and column names provided exists in a that collection and if everything is fine go and update the collection.I was able to check if a collection exists or not but failed in doing the same for Columns.
I found this in Mongodb website
{ item : { $exists: false } }
but i didn't found the exact c# code for doing the same. Is it possible with c# to check if a column exists in MongoDb ? MongoDb version 4.0 is what i am using now.
Note : I don't have any strongly typed data, Since the function is unaware of the collection and the type of data it holds. The goal is to accept column names and values and update to those fields that have passed to it.

If you want to find documents where a property doesn't exist, you can use the following code:
var modelsWithoutItem = collection.Find(
Builders<DocModel>.Filter.Exists(m => m.Item, false)
);
or if you don't have strongly typed data:
var modelsWithoutItem = collection.Find(
Builders<BsonDocument>.Filter.Exists("item", false)
);

var fieldExists = _collection.Find(Builders<BsonDocument>.Filter.Exists("item",true));
if (fieldExists.CountDocuments() > 0){
// yes document with this field is available
}else{
// No documents with that field name exists
}
#john Thank you for the quick response, with a bit of update i have got what I wanted.

Related

CosmosDB SQL API: Change property Name - (Partial Updates .Net SDK or loops)

Consider the following data
I am trying to update the property name from givenName to PetName. Below are the things I tried.
Option 1:
List<PatchOperation> patchOperations = new List<PatchOperation>();
dynamic data = new
{
PetName= "Dummy"
};
//Remove the 0th element from the pet array
patchOperations.Add(PatchOperation.Remove("/children/0/pets/0"));
//insert the new entity
patchOperations.Add(PatchOperation.Add<dynamic>("/children/0/pets/0", data));
await Container.PatchItemAsync<dynamic>("AndersenFamily", new
PartitionKey("AndersenFamily"), patchOperations);
This works on the first element (as I have specified the index as 0).
But I couldn't find a way to update all the elements in the array. Something like /children/*/pets (I get an error "Invalid navigation for array(*)").
Option 2:
Read all the data from the database, remove the existing pets and upload the new object with the property PetName. But I guess it will take lot of time to loop through all the objects and make these changes.
Can someone suggest a better solution or a way to fix the partial updates so that it updates all the elements in the array?
The actual dataset that I am working on is huge and has more nested arrays.
Yes you are right, Current version of Patch does not support patching nested array. You need to know the index in order to replace/add values as you mentioned in the first question.
One way to think about this would be to write your own logic to replace the keys , there are libraries available in dotnet and then using the bulk insert using the SDK to insert those documents.

How to query field equals empty array?

I have an array field in my collection which have value with properties or empty value as "[]"
For fetching the documents having empty "[]" value in mongodb i use
db.getCollection('collection').find({"ArrayFieldName":{$eq:[]}})
This gives me result as expected. But when i try to form this query in the C# using mongodb driver i couldnt get the expected Result.
I tried,
filterBuilder.Eq("ArraryFieldName", "[]") and filterBuilder.Eq("ArraryFieldName", new ArraryClassName(){})
Need help with C# filter builder to specify $eq:[] for arrary field.
An instance of ArraryClassName clearly won't work because it's not an array instance - it's a single object. Likewise "[]" won't work because it's a string.
You can check directly translate your CLI query to this filter:
Builders<BsonDocument>.Filter.Eq<BsonArray>("ArraryFieldName", new BsonArray())
Though if you simply want to check that the existing array is empty, you can use this filter instead:
Builders<BsonDocument>.Filter.Size("ArraryFieldName", 0)
P.S. I would strongly suggest using C# data models as it makes everything much easier to work with.
Also, you have called your field ArraryFieldName (notice the extra r at the end of Array). If you don't have existing data with this misspelled property name, you might want to correct the spelling.

Simple Existing Document Update in Elasticsearch using NEST

Hey I trying to update existing document of ElasticSearch, I found a cURL code from Elasticsearch site
Note: Sam type with 2 document is already exists I just want to update a existing field
POST /EmployeeIndex/Sam/2/_update
{
"doc" : {
"Nested" : true,
"views": 0
}
}
Its working perfectly how I need but please help me to convert it to NEST, as i working on .NET, I managed to write a code
var responseUpdate = client.Update<clsEmployeeElasticSearch, object>(u => u
.Index("EmployeeIndex")
.Type("Sam")
.Id(2)
.Doc(new { Nested= true })
.RetryOnConflict(3)
.Refresh());
But it always creating a new field in my document instead of updating existing one.
Please see attached screenshot with a code
Please help guys.
What you need is a PartialUpdate. Applied on your example, the following code should do what you expect.
var responseUpdate = client.Update<clsEmployeeElasticSearch, object>(u => u
.Index("EmployeeIndex")
.Type("Sam")
.Id(2)
.Doc(new {IsActive ="true", Views="0"})
.DocAsUpsert()
);
Is it possible that you are already there but be just facing a casing missmatch issue? see from Nest reference:
Property Name Inference In many places NEST allows you to pass
property names and JSON paths as C# expressions, i.e:
.Query(q=>q
.Term(p=>p.Followers.First().FirstName, "martijn")) NEST by default will camelCase properties. So the FirstName property above
will be translated to "followers.firstName".
This can be configured by setting
settings.SetDefaultPropertyNameInferrer(p=>p); This will leave
property names untouched.
Properties marked with [ElasticAttibute(Name="")] or
[JsonProperty(Name="")] will pass the configured name verbatim.
...
Note that you are creating a dynamic object for the update so, i belive attributes might not a be a solution if you keep it that way

Mongo single upsert to add or update a field in c#

I was trying to do something that it would be nice if it was supported, but appears not to be.
I would like to be able to update a record if it exists, and if not set the field to a default value. Specifically, I am using .AddToSet() to append an object to a list.
This will not work:
UpdateBuilder<TestDocument> update = Update<TestDocument>
.Set(d => d.UpdatedOn, DateTime.Now)
.SetOnInsert(d => d.ListOfItems, new List<Item> () {ItemToAdd})
.AddToSet(d => d.ListOfItems, ItemToAdd);
TestCollection.Update(query,update, UpdateFlags.Upsert);
What I would expect:
On an update just add the record to the end of the existing list.
If it doesn't exist, have it do one of the following:
Set the field to the value, and ignore the update.
Set the field to the value, and then do the update. (so, I would change the code to do
SetOnInsert (d => d.ListOfItems, new List< Item> ())
But instead, it throws an error that the field is specified twice.
I could (and have) fixed this by doing a search first, if not found, do a upsert with the first record. If that returns 0 documents affected (someone else upserted it.) then I fall back and do the upsert - which of course, is also done if the document exists.
Is there a cleaner way? Or ideally, doing it in a single command?
SetOnInsert is only necessary when you want something to only apply on insert. In this case, you want the AddToSet to apply whether it's an update or an upsert. So, if you just use AddToSet, it will accomplish what you want.

Comparing two datasources in C#

I have a gridview, bound to a datasource whose database table contains a foreign key that is associated with the database table that is used as the datasource for a dropdownlist.
What I want to do is if a certain foreignKeyId exists in gridview.datasource, to remove it from dropdownlist.datasource.
To give a clearer idea of what/why I want what I want, the user is able to add entries to the gridview (and therefore the datasource), but I don't want the user to be able to make more than one entry for a specific type. Is there a way that a linq query could do this?
pseudocode (note that I know RemoveObjects() is an invalid method)
var query = DataContext.Items.Where(item => item.TypeId == selectedTypeId);
dropDownList.DataSource.RemoveObjects(query);
Here is how I bind the dropdownlist, so maybe I could do something here to not get the items with already existing TypeId's?
dropDownList.DataSource = DataContext.Items.Select(items => new
{
items.Name,
items.TypeId,
}).ToList();
Any suggestions or answers would be great!
Have you tried using except
dropDownList.DataSource.Except(query)

Categories