LINQ to JSON - SelectToken Error - c#

This is the JSON string that I am working with.
string jsonText = "{
"?xml" : {
"#version" : "1.0",
"#encoding" : "UTF-8",
"#standalone" : "yes"
},
"Grid" : {
"DataRow" : [{
"DataItem" : [{
"#name" : "SYMBOL",
"#text" : "005930"
}, {
"#name" : "NAME",
"#text" : "Samsung Electronics"
}, {
"#name" : "PRICE",
"#text" : "1004.3"
}, {
"#name" : "VOLUME",
"#text" : "273.182"
}, {
"#name" : "AGG_VOLUME",
"#text" : "302.894"
}
]
}, {
"DataItem" : [{
"#name" : "SYMBOL",
"#text" : "AAPL"
}, {
"#name" : "NAME",
"#text" : "Apple Inc."
}, {
"#name" : "PRICE",
"#text" : "99"
}, {
"#name" : "VOLUME",
"#text" : "32936.4"
}, {
"#name" : "AGG_VOLUME",
"#text" : "33078.769"
}
]
}, {
"DataItem" : [{
"#name" : "SYMBOL",
"#text" : "MSFT"
}, {
"#name" : "NAME",
"#text" : "Microsoft Corporation"
}, {
"#name" : "PRICE",
"#text" : "42"
}, {
"#name" : "VOLUME",
"#text" : "103441.6"
}, {
"#name" : "AGG_VOLUME",
"#text" : "1324432.074"
}
]
}
]
}
}"
JObject feed = JObject.Parse(jsonText);
I'm trying to get a list of values for SYMBOL, NAME, PRICE, & AGG_VOLUME. Here's my code so far:
var covg = feed["DataItem"]["#name"].Select(f => (string)f.SelectToken("#text"));
But I'm getting the following error:
Object reference not set to an instance of an object.
What am I doing wrong?

JToken.SelectTokens() supports JSONPath query syntax. You can make use of this syntax to perform the query you require:
".." is the wildcard recursive descent operator. Thus feed.SelectTokens("..DataItem") finds the values of all JSON properties named DataItem no matter where they are in the JSON hierarchy.
"[?(#.#name == 'Value')]" queries for objects in an array with a property named #name with value Value.
Thus, the following does what you need:
var feed = JObject.Parse(jsonText);
var query = from item in feed.SelectTokens("..DataItem")
select new
{
SYMBOL = (string)item.SelectToken("[?(#.#name == 'SYMBOL')].#text"),
NAME = (string)item.SelectToken("[?(#.#name == 'NAME')].#text"),
PRICE = (string)item.SelectToken("[?(#.#name == 'PRICE')].#text"),
AGG_VOLUME = (string)item.SelectToken("[?(#.#name == 'AGG_VOLUME')].#text")
};
var list = query.ToList();

You are getting this error because feed refers to the root JObject which does not directly contain a DataItem property. Thus feed["DataItem"] returns null. When you then try to dereference this null expression it throws a NullReferenceException.
The data you are trying to get is several layers down in the JSON, so your query has to account for this. To get a list of all SYMBOL values in the JSON, for example, you would need to do something like this:
List<string> symbols =
feed.SelectToken("Grid.DataRow")
.SelectMany(jt => jt["DataItem"])
.Where(jt => (string)jt["#name"] == "SYMBOL")
.Select(jt => (string)jt["#text"])
.ToList();
Fiddle: https://dotnetfiddle.net/jxZGZC

Related

C# Retrieving a specific piece of information from JSON string by using Newtonsoft.json

JSON string that i retrieved:
{
"trackItemResponse" : {
"hdr" : {
"messageType" : "TRACKITEM",
"messageDateTime" : "2021-04-28T16:32:05+08:00",
"messageVersion" : "1.0",
"messageLanguage" : "en"
},
"bd" : {
"shipmentItems" : [ {
"masterShipmentID" : null,
"shipmentID" : "MYCGUMY8202104SIN00005",
"trackingID" : "5021049762931421",
"orderNumber" : null,
"handoverID" : null,
"shippingService" : {
"productCode" : "PDO",
"productName" : "Parcel Domestic"
},
"consigneeAddress" : {
"country" : "MY"
},
"weight" : "804",
"dimensionalWeight" : "640",
"weightUnit" : "G",
"events" : [ {
"status" : "77093",
"description" : "Successfully delivered",
"dateTime" : "2021-04-06 13:47:56",
"timezone" : "LT",
"address" : {
"city" : "Skudai",
"postCode" : "81300",
"state" : "JOHOR",
"country" : "MY"
}
}, {
"status" : "77090",
"description" : "Out for Delivery",
"dateTime" : "2021-04-06 10:51:55",
"timezone" : "LT",
"address" : {
"city" : "Skudai",
"postCode" : "81300",
"state" : "JOHOR",
"country" : "MY"
}
}, {
"status" : "77184",
"description" : "Processed at delivery facility",
"dateTime" : "2021-04-06 07:56:07",
"timezone" : "LT",
"address" : {
"city" : "Skudai",
"postCode" : "81300",
"state" : "Johor",
"country" : "MY"
}
}, {
"status" : "77178",
"description" : "Arrived at facility",
"dateTime" : "2021-04-06 07:30:26",
"timezone" : "LT",
"address" : {
"city" : "Skudai",
"postCode" : "81300",
"state" : "Johor",
"country" : "MY"
}
}, {
"status" : "77169",
"description" : "Departed from facility",
"dateTime" : "2021-04-06 05:22:02",
"timezone" : "LT",
"address" : {
"city" : "Kuala Lumpur Hub",
"postCode" : "47100",
"state" : "Kuala Lumpur",
"country" : "MY"
}
}, {
"status" : "77027",
"description" : "Sorted to delivery facility",
"dateTime" : "2021-04-05 21:00:05",
"timezone" : "LT",
"address" : {
"city" : "Kuala Lumpur Hub",
"postCode" : "47100",
"state" : "Kuala Lumpur",
"country" : "MY"
}
}, {
"status" : "77015",
"description" : "Processed at facility",
"dateTime" : "2021-04-05 20:59:04",
"timezone" : "LT",
"address" : {
"city" : "Kuala Lumpur Hub",
"postCode" : "47100",
"state" : "Kuala Lumpur",
"country" : "MY"
}
}, {
"status" : "71005",
"description" : "DATA SUBMITTED",
"dateTime" : "2021-04-02 15:44:40",
"timezone" : "Malaysia",
"address" : {
"city" : "SEPANG, SELANGOR",
"postCode" : "43900",
"state" : "SEL",
"country" : "MY"
}
} ]
} ],
"responseStatus" : {
"code" : "200",
"message" : "SUCCESS",
"messageDetails" : [ {
"messageDetail" : "1 tracking reference(s) tracked, 1 tracking reference(s) found."
} ]
}
}
}
}
Output that i wanted:
5021049762931421 //trackingID
Method_1 that i've tried:
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string result = streamReader.ReadToEnd();
Console.WriteLine(result);
dynamic data = JObject.Parse(result);
Console.WriteLine(data.trackItemResponse.bd.shipmentItems.trackingID);
}
Output:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''Newtonsoft.Json.Linq.JArray' does not contain a definition for 'trackingID''
Method_2 that i've tried:
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var trckID = JObject.Parse(result)["trackItemResponse"]["bd"]["shipmentItems"].Select(x => (string)x["trackingID"]).ToList();
Console.WriteLine("Below is json data");
Console.WriteLine(trckID);
Console.WriteLine("Until here la");
}
Output_2:
Below is json data
System.Collections.Generic.List`1[System.String]
Until here la
Method_3 that i've tried:
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string jsonData = JObject.Parse(result)["trackItemResponse"]["bd"]["shipmentItems"]["trackingID"].ToString();
Console.WriteLine("Below is json data");
Console.WriteLine(jsonData);
Console.WriteLine("Until here la");
}
Output_3:
System.ArgumentException: 'Accessed JArray values with invalid key value: "trackingID". Int32 array index expected.'
Is there any other methods that could work? Thank you.
Post that i've refered
Convert string to int C#
C# cast from string to int/int32
Make newtonsoft.json convert default to int32 rather than int64
C# extract json array with newtonsoft.json
Thank you for your kind assistance!
You are looking for
var result = JObject.Parse(result)["trackItemResponse"]["bd"]["shipmentItems"][0]["trackingID"].ToString();
But keep in mind that shipmentItems is a list, so could contain multiple items.
This code only checks the first in that list.
SelectToken is what you are looking for:
var semiParsedJson = JObject.Parse(json);
var trackingId = semiParsedJson
.SelectToken("trackItemResponse.bd.shipmentItems[0].trackingID");
Please bear in mind that this solution assumes that the first object in the shipmentItems collection contains the required information.
If it is not present then trackingId will be null.
If you have multiple objects inside the shipmentItems and you are interested about all of the trackingId values then you have to use SelectTokens
var semiParsedJson = JObject.Parse(json);
var trackingIds = semiParsedJson
.SelectTokens("trackItemResponse.bd.shipmentItems[*].trackingID");
Please note that the indexer operator now receives a * wildcard.
From your code, you are almost there.
Since the object "data.trackItemResponse.bd.shipmentItems" is an array, you need to access the "trackingID" after selecting the index.
Your code should be:
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
string result = streamReader.ReadToEnd();
Console.WriteLine(result);
dynamic data = JObject.Parse(result);
//Test this
var trackingID = data.trackItemResponse.bd.shipmentItems[0].trackingID;
Console.WriteLine(data.trackItemResponse.bd.shipmentItems[0].trackingID);
}

MongoDb - Joining ObjectId references in the list with related collections [duplicate]

I have the following MongoDb query working:
db.Entity.aggregate(
[
{
"$match":{"Id": "12345"}
},
{
"$lookup": {
"from": "OtherCollection",
"localField": "otherCollectionId",
"foreignField": "Id",
"as": "ent"
}
},
{
"$project": {
"Name": 1,
"Date": 1,
"OtherObject": { "$arrayElemAt": [ "$ent", 0 ] }
}
},
{
"$sort": {
"OtherObject.Profile.Name": 1
}
}
]
)
This retrieves a list of objects joined with a matching object from another collection.
Does anybody know how I can use this in C# using either LINQ or by using this exact string?
I tried using the following code but it can't seem to find the types for QueryDocument and MongoCursor - I think they've been deprecated?
BsonDocument document = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{ name : value }");
QueryDocument queryDoc = new QueryDocument(document);
MongoCursor toReturn = _connectionCollection.Find(queryDoc);
There is no need to parse the JSON. Everything here can actually be done directly with either LINQ or the Aggregate Fluent interfaces.
Just using some demonstration classes because the question does not really give much to go on.
Setup
Basically we have two collections here, being
entities
{ "_id" : ObjectId("5b08ceb40a8a7614c70a5710"), "name" : "A" }
{ "_id" : ObjectId("5b08ceb40a8a7614c70a5711"), "name" : "B" }
and others
{
"_id" : ObjectId("5b08cef10a8a7614c70a5712"),
"entity" : ObjectId("5b08ceb40a8a7614c70a5710"),
"name" : "Sub-A"
}
{
"_id" : ObjectId("5b08cefd0a8a7614c70a5713"),
"entity" : ObjectId("5b08ceb40a8a7614c70a5711"),
"name" : "Sub-B"
}
And a couple of classes to bind them to, just as very basic examples:
public class Entity
{
public ObjectId id;
public string name { get; set; }
}
public class Other
{
public ObjectId id;
public ObjectId entity { get; set; }
public string name { get; set; }
}
public class EntityWithOthers
{
public ObjectId id;
public string name { get; set; }
public IEnumerable<Other> others;
}
public class EntityWithOther
{
public ObjectId id;
public string name { get; set; }
public Other others;
}
Queries
Fluent Interface
var listNames = new[] { "A", "B" };
var query = entities.Aggregate()
.Match(p => listNames.Contains(p.name))
.Lookup(
foreignCollection: others,
localField: e => e.id,
foreignField: f => f.entity,
#as: (EntityWithOthers eo) => eo.others
)
.Project(p => new { p.id, p.name, other = p.others.First() } )
.Sort(new BsonDocument("other.name",-1))
.ToList();
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"localField" : "_id",
"foreignField" : "entity",
"as" : "others"
} },
{ "$project" : {
"id" : "$_id",
"name" : "$name",
"other" : { "$arrayElemAt" : [ "$others", 0 ] },
"_id" : 0
} },
{ "$sort" : { "other.name" : -1 } }
]
Probably the easiest to understand since the fluent interface is basically the same as the general BSON structure. The $lookup stage has all the same arguments and the $arrayElemAt is represented with First(). For the $sort you can simply supply a BSON document or other valid expression.
An alternate is the newer expressive form of $lookup with a sub-pipeline statement for MongoDB 3.6 and above.
BsonArray subpipeline = new BsonArray();
subpipeline.Add(
new BsonDocument("$match",new BsonDocument(
"$expr", new BsonDocument(
"$eq", new BsonArray { "$$entity", "$entity" }
)
))
);
var lookup = new BsonDocument("$lookup",
new BsonDocument("from", "others")
.Add("let", new BsonDocument("entity", "$_id"))
.Add("pipeline", subpipeline)
.Add("as","others")
);
var query = entities.Aggregate()
.Match(p => listNames.Contains(p.name))
.AppendStage<EntityWithOthers>(lookup)
.Unwind<EntityWithOthers, EntityWithOther>(p => p.others)
.SortByDescending(p => p.others.name)
.ToList();
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"let" : { "entity" : "$_id" },
"pipeline" : [
{ "$match" : { "$expr" : { "$eq" : [ "$$entity", "$entity" ] } } }
],
"as" : "others"
} },
{ "$unwind" : "$others" },
{ "$sort" : { "others.name" : -1 } }
]
The Fluent "Builder" does not support the syntax directly yet, nor do LINQ Expressions support the $expr operator, however you can still construct using BsonDocument and BsonArray or other valid expressions. Here we also "type" the $unwind result in order to apply a $sort using an expression rather than a BsonDocument as shown earlier.
Aside from other uses, a primary task of a "sub-pipeline" is to reduce the documents returned in the target array of $lookup. Also the $unwind here serves a purpose of actually being "merged" into the $lookup statement on server execution, so this is typically more efficient than just grabbing the first element of the resulting array.
Queryable GroupJoin
var query = entities.AsQueryable()
.Where(p => listNames.Contains(p.name))
.GroupJoin(
others.AsQueryable(),
p => p.id,
o => o.entity,
(p, o) => new { p.id, p.name, other = o.First() }
)
.OrderByDescending(p => p.other.name);
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"localField" : "_id",
"foreignField" : "entity",
"as" : "o"
} },
{ "$project" : {
"id" : "$_id",
"name" : "$name",
"other" : { "$arrayElemAt" : [ "$o", 0 ] },
"_id" : 0
} },
{ "$sort" : { "other.name" : -1 } }
]
This is almost identical but just using the different interface and produces a slightly different BSON statement, and really only because of the simplified naming in the functional statements. This does bring up the other possibility of simply using an $unwind as produced from a SelectMany():
var query = entities.AsQueryable()
.Where(p => listNames.Contains(p.name))
.GroupJoin(
others.AsQueryable(),
p => p.id,
o => o.entity,
(p, o) => new { p.id, p.name, other = o }
)
.SelectMany(p => p.other, (p, other) => new { p.id, p.name, other })
.OrderByDescending(p => p.other.name);
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"localField" : "_id",
"foreignField" : "entity",
"as" : "o"
}},
{ "$project" : {
"id" : "$_id",
"name" : "$name",
"other" : "$o",
"_id" : 0
} },
{ "$unwind" : "$other" },
{ "$project" : {
"id" : "$id",
"name" : "$name",
"other" : "$other",
"_id" : 0
}},
{ "$sort" : { "other.name" : -1 } }
]
Normally placing an $unwind directly following $lookup is actually an "optimized pattern" for the aggregation framework. However the .NET driver does mess this up in this combination by forcing a $project in between rather than using the implied naming on the "as". If not for that, this is actually better than the $arrayElemAt when you know you have "one" related result. If you want the $unwind "coalescence", then you are better off using the fluent interface, or a different form as demonstrated later.
Querable Natural
var query = from p in entities.AsQueryable()
where listNames.Contains(p.name)
join o in others.AsQueryable() on p.id equals o.entity into joined
select new { p.id, p.name, other = joined.First() }
into p
orderby p.other.name descending
select p;
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"localField" : "_id",
"foreignField" : "entity",
"as" : "joined"
} },
{ "$project" : {
"id" : "$_id",
"name" : "$name",
"other" : { "$arrayElemAt" : [ "$joined", 0 ] },
"_id" : 0
} },
{ "$sort" : { "other.name" : -1 } }
]
All pretty familiar and really just down to functional naming. Just as with using the $unwind option:
var query = from p in entities.AsQueryable()
where listNames.Contains(p.name)
join o in others.AsQueryable() on p.id equals o.entity into joined
from sub_o in joined.DefaultIfEmpty()
select new { p.id, p.name, other = sub_o }
into p
orderby p.other.name descending
select p;
Request sent to server:
[
{ "$match" : { "name" : { "$in" : [ "A", "B" ] } } },
{ "$lookup" : {
"from" : "others",
"localField" : "_id",
"foreignField" : "entity",
"as" : "joined"
} },
{ "$unwind" : {
"path" : "$joined", "preserveNullAndEmptyArrays" : true
} },
{ "$project" : {
"id" : "$_id",
"name" : "$name",
"other" : "$joined",
"_id" : 0
} },
{ "$sort" : { "other.name" : -1 } }
]
Which actually is using the "optimized coalescence" form. The translator still insists on adding a $project since we need the intermediate select in order to make the statement valid.
Summary
So there are quite a few ways to essentially arrive at what is basically the same query statement with exactly the same results. Whilst you "could" parse the JSON to BsonDocument form and feed this to the fluent Aggregate() command, it's generally better to use the natural builders or the LINQ interfaces as they do easily map onto the same statement.
The options with $unwind are largely shown because even with a "singular" match that "coalescence" form is actually far more optimal then using $arrayElemAt to take the "first" array element. This even becomes more important with considerations of things like the BSON Limit where the $lookup target array could cause the parent document to exceed 16MB without further filtering. There is another post here on Aggregate $lookup Total size of documents in matching pipeline exceeds maximum document size where I actually discuss how to avoid that limit being hit by using such options or other Lookup() syntax available to the fluent interface only at this time.

..ToBsonDocument() is extremly slow (60ms)

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",
}
]
}

MongoWriteException: A write operation resulted in an error. The positional operator did not find the match needed from the query

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.

mongoDB insert item in Array

{
"_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. **

Categories

Resources