{
"_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. **
Related
I'm having difficulties putting up a code which returns an element in an array of subdocuments. I am actually trying to flatten a document to a new document which is strongly typed. My document is looking like;
{
"_id" : BinData(3, "7FRf4nbe60ev6XmGKBBW4Q=="),
"status" : NumberInt(1),
"title":"Central station",
"attributes" : [
{
"defId" : BinData(3, "QFDtR03NbkqwuhhG76wS8g=="),
"value" : "388",
"name" : null
},
{
"defId" : BinData(3, "RE3MT3clb0OdLEkkqhpFOg=="),
"value" : "",
"name" : null
},
{
"defId" : BinData(3, "pPgJR50h8kGdDaCcH2o17Q=="),
"value" : "Merkez",
"name" : null
}
]}
What I am trying to achieve is;
{
"title":"Central Station",
"value":"388"
}
What I've done already;
using (_dbContext)
{
var filter = Builders<CustomerModel>.Filter.Eq(q => q.Id, Guid.Parse("30B59585-CBFC-4CD5-A43E-0FDB0AE3167A")) &
Builders<CustomerModel>.Filter.ElemMatch(f => f.Attributes, q => q.DefId == Guid.Parse("47ED5040-CD4D-4A6E-B0BA-1846EFAC12F2"));
var projection = Builders<CustomerModel>.Projection.Include(f => f.Title).Include("attributes.value");
var document = _dbContext.Collection<CustomerModel>().Find(filter).Project(projection).FirstOrDefault();
if (document == null)
return null;
return BsonSerializer.Deserialize<TitleAndValueViewModel>(document);
}
Note: TitleAndCodeViewModel contains title and value properties.
This block of code returns;
{{ "_id" : CSUUID("30b59585-cbfc-4cd5-a43e-0fdb0ae3167a"), "title" : "388 güvenevler", "attributes" : [{ "value" : "388" }, { "value" : "" }, { "value" : "Merkez " }] }}
I am trying to get "value":"388" but instead I am getting another two value properties even tough the ElemMatch filter added for subdocument.
Thank you for your help in advance.
Note: I am looking for answers in C# mongodb driver.
Option 1: ( via aggregation)
db.collection.aggregate([
{
$match: {
_id: 5,
"attributes.defId": 1
}
},
{
"$addFields": {
"attributes": {
"$filter": {
"input": "$attributes",
"as": "a",
"cond": {
$eq: [
"$$a.defId",
1
]
}
}
}
}
},
{
$unwind: "$attributes"
},
{
$project: {
_id: 0,
title: 1,
value: "$attributes.value"
}
}
])
Explained:
Match ( good to add index for the matching fields )
Filter only the attribute you need
Unwind to convert the array to object
Project only the necessary output
Playground
Option 2: ( find/$elemMatch )
db.collection.find({
_id: 5,
attributes: {
"$elemMatch": {
"defId": 1
}
}
},
{
_id: 0,
title: 1,
"attributes": {
"$elemMatch": {
"defId": 1
}
}
})
Explained:
Match the element via _id and elemMatch the attribute
Project the necessary elements. ( Note here elemMatch also need to be used to filter the exact match attribute )
( Note this version will not identify if there is second attribute with same attribute.defId , also projection of attribute will be array with single element if found that need to be considered from the app side )
Playground 2
by specifying defId
db.collection.aggregate(
[{
$project: {
title: '$title',
attributes: {
$filter: {
input: '$attributes',
as: 'element',
cond: { $eq: ['$$element.defId', BinData(3, 'QFDtR03NbkqwuhhG76wS8g==')] }
}
}
}
}, {
$project: {
_id: 0,
title: '$title',
value: { $first: '$attributes.value' }
}
}])
result:
{
"title": "Central station",
"value": "388"
}
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",
}
]
}
{
"_id" : {
"order" : "0000006"
},
"Catgeory" : [
{
"ID" : "62982698",
"Data" : [
{
"NO" : "62982698",
"History" : [
{
"Status" : null,
}
]
}
]
},
{
"ID" : "63002696",
"Data" : []
}
],
"Info_ID" : [
"6000016405"
]
}
How to write c# mongo filter to get No:62982698 with "Info_ID" :"6000016405". No:62982698 can be part of multiple documents.So want to write filter that filters document with No 62982698 and "Info_ID" :"6000016405"
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.
Im dba and development a C# Web App to get information from Mongodb, but when i try to get information from an array attribute, the C# show me all element of the document that contain the element that i find. I just want to get the specific element, not all.
I have this document:
{
"_id" : ObjectId("53b1b7dcb830980744687bd4"),
"i_nombre" : "Centro Comercial",
"i_direccion" : {
"i_d_pais" : "Panamá",
"i_d_ciudad" : "Panamá",
"i_d_provincia" : "Panamá",
"i_d_distrito" : "Chilibre",
"i_d_corregimiento" : "Alcalde Diaz",
"i_d_calle" : "Primera"
},
"i_correo_e" : "imqv#imqv.com.pa",
"i_telefono" : {
"i_t_iglesia" : "268-5000",
"i_t_colegio" : "268-5001",
"i_t_radio" : "268-5002"
},
"i_estado" : 1,
"i_sector" : [
{
"_id" : ObjectId("53b6d903b8309826e891eefe"),
"i_s_color" : "Amarillo",
"i_s_localizacion" : {
"i_s_l_provincia" : "Panamá",
"i_s_l_distrito" : "Chilibre",
"i_s_l_corregimiento" : "San Miguelito"
},
"i_s_supervisor" : []
},
{
"_id" : ObjectId("53b6d903b8309826e89100f0"),
"i_s_color" : "Rojo",
"i_s_localizacion" : {
"i_s_l_provincia" : "Panamá",
"i_s_l_distrito" : "Arraijan",
"i_s_l_corregimiento" : "Burunga"
},
"i_s_supervisor" : []
},
{
"_id" : ObjectId("53b6d903b8309826e89220f0"),
"i_s_color" : "Azul",
"i_s_localizacion" : {
"i_s_l_provincia" : "Panamá",
"i_s_l_distrito" : "Colon",
"i_s_l_corregimiento" : "Chilibre"
},
"i_s_supervisor" : []
}
]
};
When i execute this query on mongodb
db.iglesia.find
(
{ "_id" : ObjectId("53b1b7dcb830980744687bd4") }
, {
i_sector: {
$elemMatch: { "_id" : ObjectId("53b6d903b8309826e891eefe") }
}
}
);
i get:
{
"_id" : ObjectId("53b1b7dcb830980744687bd4"),
"i_sector" : [
{
"_id" : ObjectId("53b6d903b8309826e891eefe"),
"i_s_color" : "Amarillo",
"i_s_localizacion" : {
"i_s_l_provincia" : "Panamá",
"i_s_l_distrito" : "Chilibre",
"i_s_l_corregimiento" : "San Miguelito"
},
"i_s_supervisor" : []
}
]
}
Question: How i can get the same result with C#? Just with the $elemMatch that i set on Query.
The reason is that your Mongo shell query is not a find with 2 filters, by church id and sector, it is actually a find by church id and a projection by sector id. You have arranged the braces funny, that's all.
This has 2 filters and no projection:
db.iglesia.find ({"_id": "53b1b7dcb830980744687bd4", i_sector: { $elemMatch: {"_id" : "53b6d903b8309826e891eefe"}}}).pretty()
This has a filter and projection:
db.iglesia.find ({"_id": "53b1b7dcb830980744687bd4"}, {i_sector: { $elemMatch: { "_id": "53b6d903b8309826e891eefe"}}}).pretty()
A complete C# example, for these 2 cases using a newer driver, version 2.3, here on rextester.