I'm trying to update just a few nested documents on my .Net Application, but I don't know exactly how to do that.
Here is one of the topics I've been searching after making this question:
C# - MongoDB - Update an element inside a Nested Document
**DataBase Object: **
{
"_id" : ObjectId("5d03a6f5fba276260c4911bd"),
"costumerId" : ObjectId("5c050cdefba2771eac58c84b"),
"order" : 106376,
"items" : [
{
"itemId" : 10226905,
"date" : ISODate("2018-11-30T14:00:00.000Z"),
"description" : "itemA",
"new" : true,
},
{
"itemId" : 10226906,
"date" : ISODate("2018-11-30T14:00:00.000Z"),
"description" : "itemB",
"new" : true,
},
{
"itemId" : 10226907,
"date" : ISODate("2018-11-23T14:00:00.000Z"),
"description" : "ItemC",
"new" : true,
},
{
"itemId" : 10226908,
"date" : ISODate("2018-11-23T14:00:00.000Z"),
"description" : "ItemD",
"new" : false,
},
]
}
MongoDB Update Query:
db.CostumerProducts.update(
{costumerId: 106376},
{
$set:{'items.$[element].new': true}
},
{
multi:true,
arrayFilters: [
{
'element.itemId':{
$in:[10226905,10226906,10226907]
}
}]
})
C# Update Query using MongoDB driver:
var arrayObjects = List<int>{10226905,10226906,10226907};
var filter = Builders<CostumerProductsObject>.Filter.And(new[]
{
new FilterDefinitionBuilder<CostumerProductsObject>().Eq(p=>p.costumerId, costumerId),
new FilterDefinitionBuilder<CostumerProductsObject>().Eq(p=>p.order, order),
});
var set = Builders<ItemsObject>.Update.Set("items.$[element].new", true);
var arrayFilter = new FilterDefinitionBuilder<ItemsObject>().In(a=>a.itemId, itemsArray);
using (var db = new MongoContextInfra())
{
db.Set<CostumerProductsObject>(CollectionName).UpdateMany(filter,
set,
new UpdateOptions
{
ArrayFilters = null
});
}
I expect to update just the three items into "arrayObjects" variable.
Can you show me some code or help me fixing mine so I can make this update?
thanks.
Related
I am trying to add a json item to an array exist in json object to save it on mongodb using c#
i have this element
{
"_id" : ObjectId("5cf67ad97739bfe8525e5353"),
"Email" : "eyal#gmail.com",
"Username" : "eyal",
"Password" : "1234",
"Tokens" : [
{
"Tokennumber" : "123",
"Valid" : "true",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
},
{
"Tokennumber" : "124",
"Valid" : "false",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
}
]
}
i want to add a token item to tokens array using c#
i have this code querying the requested item
var client = new MongoDB.Driver.MongoClient();
var db = client.GetDatabase("SupaFoo");
var _users = db.GetCollection<Users>("Users");
var user =
(from u in _users.AsQueryable<Users>()
where u.email == login.Email && u.password == login.Password
select u).ToList();
the new item sholud be like this
{
"_id" : ObjectId("5cf67ad97739bfe8525e5353"),
"Email" : "eyal#gmail.com",
"Username" : "eyal",
"Password" : "1234",
"Tokens" : [
{
"Tokennumber" : "123",
"Valid" : "true",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
},
{
"Tokennumber" : "124",
"Valid" : "false",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
},
{/* newly added item */
"Tokennumber" : "555",
"Valid" : "true",
"LoginDate" : ISODate("2019-06-05T00:00:00.000Z")
}
]
}
You can atomically add items to an objects array using the AddToSet (docs here) method
var updateDefinition = Builders<Users>.Update.AddToSet(x => x.Tokens, new Token());
var filterDefinition = Builders<Users>.Filter.Eq(x => x.Id, userId);
_users.UpdateOne(filterDefinition, updateDefinition);
I am afraid you have to deserialize it first, unless you want to do some complex string manipulation. For example:
var user= JsonConvert.DeserializeObject<User>(yourJson);
user.Tokens.Add(new Token());
var _users = db.GetCollection<Users>("Users"); // if you have this initialized before re-use it
var filter = Builders<User>.Filter.Eq(s => s.Id, user.Id);
var result = await collection.ReplaceOneAsync(filter, user)
This using Json.net: https://www.newtonsoft.com/json
Im trying to convert a BsonElement to BsonDocument, so i can use TryGetValue();. But that takes for ever (60ms)! I can't wait that for 1 Million entries.
Is there an alternative to get Values from inside a BsonValue? Or can i make it somehow significantly faster?
all i need is a unique list of inside2 (Structure is at the end)
Now i do something like that, to get Values from Array.
//Maybe this code right here is not working, but you get the idea
// convert to doc -> get value -> convert to doc -> get value
BsonDocument doc = ...;
BsonValue val1;
doc.TryGetValue("files", out val1);
BsonDocument fileAsDoc = val1.ToBsonDocument();
BsonValue catetgoriesValue;
fileAsDoc.TryGetValue("Categories", out catetgoriesValue);
BsonDocument catAsDoc = catetgoriesValue.ToBsonDocument();
BsonValue data3Value;
catAsDoc.TryGetValue("data3", out data3Value);
BsonDocument data3AsDoc = data3.ToBsonDocument();
foreach(BsonElement inside in data3AsDoc){
//.....
}
this how my Bson is put together:
{
"_id": ObjectId("1234567890123"),
"language" : "DE",
"files" : [
{
"something" : 10,
"something2" : "something2..",
"Categories" : [
{
"data1" : "1234",
"data2" : "1234",
"data3" : [
{
"inside1" : false,
"inside2" : "this is what i need at the end"
},
{
"inside1" : false,
"inside2" : "this is what i need at the end"
}
]
},
[....]
{
"data1" : "1234",
"data2" : "1234",
"data3" : [
{
"inside1" : false,
"inside2" : "this is what i need at the end"
},
{
"inside1" : false,
"inside2" : "this is what i need at the end"
}
]
}
],
"something3" : "text",
"something4" : "text",
"something5" : "text",
"something6" : "text",
"something7" : "text",
}
]
}
I have a collection Zonedetails shown below. below.
I am using C# to Insert or Update a Unit to Units array. If it is an insert I can insert Area blank. If it is an update It should only update the UnitName.
{
"Code" : "Zone1",
"Name" : "ZoneName1",
"Units" : [
{
"UnitCode" : "Unitcode1",
"UnitName" : "UnitCodeName",
"Areas" : [
{
"AreaCode" : "AreaCode1",
"AreaName" : "AreaName1"
}
]
}
]
}
{
"Code" : "Zone2",
"Name" : "ZoneName2",
"Units" : [
{
"UnitCode" : "UnitCode2",
"UnitName" : "UnityName2",
"Areas" : [
{
"AreaCode" : "Areacode2",
"AreaName" : "AreaName2"
}
]
}
]
}
{
"Code" : "Zone3",
"Name" : "ZoneName3",
"Units" : [
{
"UnitCode" : "UnitCode3",
"UnitName" : "UnitName3",
"Areas" : [
{
"AreaCode" : "Areadcode3",
"AreaName" : "AreaName3"
},
{
"AreaCode" : "AreaCode4",
"AreaName" : "Areaname4"
},
{
"AreaCode" : "AreaCode5",
"AreaName" : "Areaname5"
}
]
},
{
"UnitCode" : "UnitCode6",
"UnitName" : "UnitName6",
"Areas" : [
{
"AreaCode" : "AreaCode10",
"AreaName" : "AreaName10"
},
{
"AreaCode" : "AreaCOde11",
"AreaName" : "AreaName10"
},
{
"AreaCode" : "AreaCode12",
"AreaName" : "AreaName12"
}
]
}
]
}
I have writtent a C# code shown below. But getting "The positional operator did not find the match needed from the query"error if the Unit Code does not exist. Added not before unitCode check.
var mongoCollection = _context.GetCollection<Zone>("ZoneDetail");
var filter = Builders<Zone>.Filter.Where(x => x.Code == zoneCode && !x.Units.Any(u => u.UnitCode == unit.UnitCode));
var updateUnitCode = Builders<Zone>.Update.Set(x => x.Units.ElementAt(-1).UnitCode, unit.UnitCode);
var updateUnitName = Builders<Zone>.Update.Set(x => x.Units.ElementAt(-1).UnitName, unit.UnitName);
var result = await mongoCollection.UpdateOneAsync(filter, Builders<Zone>.Update.Combine(updateUnitCode, updateUnitName), new UpdateOptions { IsUpsert = true});
Your error message suggest that filter is not able to find matching element.
Either try to change your input or change your filter criteria.
Every day I create the index on Elastic server which is hosted on AWS. Elastic Index format is abcnoteyyyyMMdd. You can look below the mapping result of Index.I am creating the index through ElasticSearch.Nest.
Index Creation Code:
DateTime _instance = DateTime.Now;
if (!(client.IndexExists("eccnote" + _instance.ToString("yyyyMMdd"))).Exists)
{
var createIndexResult = client.CreateIndex("eccnote" + _instance.ToString("yyyyMMdd"));
var mapResult = client.Map<ESNote>(c => c.MapFromAttributes().IgnoreConflicts().Type("esnote").Indices("eccnote" + _instance.ToString("yyyyMMdd")));
}
But there is some problem, I do not know what is it? An index is being created successfully. but someday I am getting "index" : "not_analyzed" is missing from mapping results. For example here is the mapping result of Index dated 20160615. Here the result is in a proper format.
GET **indexname20160615**/_mapping?pretty
output result:-
{
"indexname" : {
"mappings" : {
"type" : {
"properties" : {
"#timestamp" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"account" : {
"type" : "string",
"index" : "not_analyzed"
},
"type" : {
"type" : "integer"
},
"userid" : {
"type" : "string",
"index" : "not_analyzed"
}
}
}
}
}
}
But when I see the mapping result of index dated 20160614,It is showing like this. Here "index" : "not_analyzed" properties is missing. It is happening for the random day only. I do not know why?
GET indexname20160614/_mapping?pretty
{
indexname20160614" : {
"mappings" : {
"indextype" : {
"properties" : {
"#timestamp" : {
"type" : "date",
"format" : "dateOptionalTime"
},
"session" : {
"type" : "string"
},
"tn" : {
"type" : "string"
},
"type" : {
"type" : "long"
},
"userid" : {
"type" : "string"
}
}
}
}
}
}
Why is it happening? Because every day through C# code, we create the index on ElasticServer but sometimes it is in proper format, sometimes it is not.
{
"_id" : ObjectId("5431f38c4ba4dd20408b0432"),
"UserID" : "1",
"Status" : {
}
},
"ListFilterType" : 1,
"IssueCategories" : [
{
"_id" : ObjectId("000000000000000000000000"),
"IssueCategoryID" : 2,
"IssueCagetoryName" : "test",
"MatchKeyword" : "test",
"MatchKeywordID" : 2
}
]
}
edit :
my expactation is like this.
{
"_id" : ObjectId("5431f38c4ba4dd20408b0432"),
"UserID" : "1",
"Status" : {
}
},
"ListFilterType" : 1,
"IssueCategories" : [
{
"_id" : ObjectId("000000000000000000000000"),
"IssueCategoryID" : 2,
"IssueCagetoryName" : "test",
"MatchKeyword" : "test",
"MatchKeywordID" : 2
},
{
"_id" : ObjectId("000000000000000000000001"),
"IssueCategoryID" : 3,
"IssueCagetoryName" : "test2",
"MatchKeyword" : "test2",
"MatchKeywordID" : 3
},
{
"_id" : ObjectId("000000000000000000000004"),
"IssueCategoryID" : 4,
"IssueCagetoryName" : "test4",
"MatchKeyword" : "test34",
"MatchKeywordID" : 4
}
]
i have a type list as "IssueCategories". You can see my mongodb structure above. If root _id = my parameter, I want to add to mongodb.
I hope I explained right
thanks
You should use either $push or $addToSet to update document.
$push will add all element in IssueCategories including duplicates also.
While in $addToSet do not insert duplicate elements(object) in array if whole object is present in array.
Using $push:
db.collection.update({
"_id": ObjectId("5431f38c4ba4dd20408b0432") // you can add any other param
}, {
$push: {
SCSIssueCategories: {
"_id": ObjectId("11111111111111111"), //ur id here
"IssueCategoryID": 3,
"IssueCagetoryName": "Sözleşme1",
"MatchKeyword": "abonelik süresi1",
"MatchKeywordID": 3
}
}
})
Here is query using $addToSet:
db.collection.update({
"_id": ObjectId("5431f38c4ba4dd20408b0432")
}, {
$addToSet: {
SCSIssueCategories: {
"_id": ObjectId("11111111111111111"), //ur id here
"IssueCategoryID": 3,
"IssueCagetoryName": "Sözleşme1",
"MatchKeyword": "abonelik süresi1",
"MatchKeywordID": 3
}
}
})
**If single param have different value then it will be inserted in array using $addToSet. **