mongodb c# how to work with BSON document - c#

I've spent MANY hours looking for the answer...
This is very easy in PHP but I just can't put it together in C#(I'm new to C# and mongo...)
I'm trying to iterate through all levels of a stored document. The document looks like this:
{
"_id": ObjectId("51f90101853bd88971ecdf27"),
"fields": [
{
"ID": ObjectId("51fd09498b080ee40c00514e"),
"NAME": "ID",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09a68b080ee40c0064db"),
"NAME": "Title",
"TYPE": "Text"
},
{
"ID": ObjectId("51fd09b28b080ee40c004d31"),
"NAME": "Start Date",
"TYPE": "Date"
},
{
"ID": ObjectId("51fd09c28b080ee40c007f2e"),
"NAME": "Long Description",
"TYPE": "Memo"
}
],
"name": "TODB",
"updated": "Wed Jul 31 2013 08:20:17 GMT-0400 (Eastern Daylight Time)"
}
I have no problem accessing the "name" and "updated" but can't figure out how to access the "fields" array.
Code so far :
{
MongoServer mongo = MongoServer.Create();
mongo.Connect();
var db = mongo.GetDatabase("forms");
mongo.RequestStart(db);
var collection = db.GetCollection("forms");
var query = new QueryDocument("name",
"TODB");
mongo.Disconnect();
}
#foreach(BsonDocument item in collection.Find(query))
{
#item.GetElement("name").Value
#item.GetElement("_id").Value
}
Again, I am able to access the name and _id just not any of the sub document values.
Thanks in advance for any assistance!
After I get the reading figured out, I am also going to want to write data....

There are a few ways, but here's one:
// build some test data
BsonArray dataFields = new BsonArray { new BsonDocument {
{ "ID" , ObjectId.GenerateNewId()}, { "NAME", "ID"}, {"TYPE", "Text"} } };
BsonDocument nested = new BsonDocument {
{ "name", "John Doe" },
{ "fields", dataFields },
{ "address", new BsonDocument {
{ "street", "123 Main St." },
{ "city", "Madison" },
{ "state", "WI" },
{ "zip", 53711}
}
}
};
// grab the address from the document,
// subdocs as a BsonDocument
var address = nested["address"].AsBsonDocument;
Console.WriteLine(address["city"].AsString);
// or, jump straight to the value ...
Console.WriteLine(nested["address"]["city"].AsString);
// loop through the fields array
var allFields = nested["fields"].AsBsonArray ;
foreach (var fields in allFields)
{
// grab a few of the fields:
Console.WriteLine("Name: {0}, Type: {1}",
fields["NAME"].AsString, fields["TYPE"].AsString);
}
You can often use the string indexer ["name-of-property"] to walk through the fields and sub document fields. Then, using the AsXYZ properties to cast the field value to a particular type as shown above.

Related

Mongo DB remove nested object

I want to remove a data in the my document. I bolded the id I want to remove
My Code like that but "This code deletes all KeyResultActions with same Id";
var filter = builder.Eq("Id", ObjectId.Parse(objectiveId))
& builder.Eq("KeyResults.Id", ObjectId.Parse(keyResultId))
& builder.Eq("KeyResults.KeyResultActions.Id", ObjectId.Parse(actionId));
var update = Builders<Objective>.Update.PullFilter("KeyResults.$[].KeyResultActions",
Builders<KeyResultAction>.Filter.Eq(x => x.Id, ObjectId.Parse(actionId)));
My document like that;
{
"_id": "**6311d1612559020ef536cb6f**",
"KeyResults": [
{
"_id": "6311d1612559020ef536cb69",
"Title": "Test KeyResult -1 ",
"Description": "Test KeyResult Desc -1",
"KeyResultActions": [
{
"_id": "630f5d4ebb4428127b11fb8e"
},
{
"_id": "630f5d4ebb4428127b11fb8f"
}
]
},
{
"_id": "**6311d1612559020ef536cb6b**",
"Title": "Test KeyResult -2",
"Description": "Test KeyResult Desc -2",
"KeyResultActions": [
{
"_id": "**630f5d4ebb4428127b11fb8e**"
},
{
"_id": "630f5d4ebb4428127b11fb8f"
}
]
}
]
}
You shouldn't use the $[] all positional operator which will remove the first item from the KeyResultActions array for all items in the KeyResults.
Instead, replace it with $ positional operator which selects the first matched element in the array.
MongoDB query
db.collection.update({
"_id": "6311d1612559020ef536cb6f",
"KeyResults._id": "6311d1612559020ef536cb6b",
"KeyResults.KeyResultActions._id": "630f5d4ebb4428127b11fb8e"
},
{
$pull: {
"KeyResults.$[].KeyResultActions": {
_id: "630f5d4ebb4428127b11fb8e"
}
}
})
MongoDB .NET Driver syntax
var update = Builders<Objective>.Update.PullFilter("KeyResults.$.KeyResultActions",
Builders<KeyResultAction>.Filter.Eq(x => x.Id, ObjectId.Parse(actionId)));
Demo

Search By Partial word of a sentence in elastic search

I am very new to Elastic Search , I want to search a result based on a partial word of a sentence , like the search string is
"val"
and it should search the result with string value
"value is grater than 100"
but if I am using a query
var searchDescriptor = new SearchDescriptor<ElasticsearchProject>()
searchDescriptor.Query(q =>
q.Wildcard(m => m.OnField(p => p.PNumber).Value(string.Format("*{0}*", searchString)))
);
it will work only for one word string like
"ValueIsGraterThan100"
if I use something like this
var searchDescriptor = new SearchDescriptor<ElasticsearchProject>()
searchDescriptor.Query(q =>
q.QueryString(m => m.OnFields(p => p.PName).Query(searchString))
);
This will work for entire word , like i have to provide search string as
"value"
to search
"value is grater than 100"
only providing val will not work.So how i can fulfill my requirement ?
Your field currently is not_analyzed, You can use edge n-gram analyzer made up of edge ngram filter to token your field before saving the fields on inverted index. You can use the following settings
PUT index_name1323
{
"settings": {
"analysis": {
"analyzer": {
"autocomplete_analyzer": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"standard",
"lowercase",
"filter_edgengram"
]
}
},
"filter": {
"filter_edgengram": {
"type": "edgeNGram",
"min_gram": 2,
"max_gram": 15
}
}
}
},
"mappings": {
"test_type": {
"properties": {
"props": {
"type": "string",
"analyzer": "autocomplete_analyzer"
}
}
}
}
}
Now you can simply use both query_string or term filter to match both your documents to val
POST index_name1323/_search
{
"query": {
"query_string": {
"default_field": "props",
"query": "val"
}
}
}
Hope this helps

How do I properly format this MongoDB update clause?

I have the following document:
{
"_id": {
"$oid": "55e1f841ff149c2228a5c33d"
},
"Status": "Open",
"Date": "8/30/2015",
"ContestName": "Test Contest",
"SearchableContestName": "test contest",
"ClassName": "Test",
"SearchableClassName": "test",
"Judges": [
{
"Name": "First Last",
"IsHeadJudge": null,
"_id": {
"$oid": "55e20962ff149c1f70d1aab0"
},
"ContestScores": null
},
{
"Name": "Another Name",
"IsHeadJudge": null,
"_id": {
"$oid": "55e20947ff149c1f70d1aaaf"
},
"ContestScores": [
1,
2,
3,
4,
5,
6
]
},
...
There are multiple judges in this list. I want to selectively update only the contest scores for the "First Last" name individual. I'm having difficulty figuring out the proper way to build my filters for this. I have:
public async void UpdateContestScores(ContestJudge judgeData, ObjectId contestId)
{
var contests = _db.GetCollection<BsonDocument>("contests");
var builder = Builders<BsonDocument>.Filter;
var updateFilter = builder.Eq("_id", contestId) & builder.Eq("Judges.Name", judgeData.Name);
var update = Builders<BsonDocument>.Update.Set("Judges.ContestScores", judgeData.ContestScores);
await contests.UpdateOneAsync(updateFilter, update);
}
This throws a bulk update error of some form. How do I go about updating this empty contest score field? I'm unsure of the proper filter syntax for such a thing.

Json nested parameters

I am using data from a Json object to populate a list view. The object has these parameters:
"id": "339150749455906",
"posts": {
"data": [
{
"id": "339150749455906_545370565500589",
"from": {
"category": "Food/beverages",
"name": "Pepsi",
"id": "339150749455906"
},
"story": "Pepsi updated their cover photo.",
"picture": "http://photos-g.ak.fbcdn.net/hphotos-ak-ash3/942740_545370555500590_46289134_s.jpg",
"link": "http://www.facebook.com/photo.php?fbid=545370555500590&set=a.365573920146922.72816.339150749455906&type=1&relevant_count=1",
"icon": "http://static.ak.fbcdn.net/rsrc.php/v2/yz/r/StEh3RhPvjk.gif",
"actions": [
{
"name": "Comment",
"link": "http://www.facebook.com/339150749455906/posts/545370565500589"
},
{
"name": "Like",
"link": "http://www.facebook.com/339150749455906/posts/545370565500589"
}
],
I want to access the link inside the parameter/key "actions". So far I am using:
foreach (var post in postsTaskResult.posts.data)
{
link = new Uri(string.Format("{0}", (string)post["link"]));
}
However, this only brings the link in the "data". How can I access the other 'link' ?
Try this.
var actionLinks = new List<string>();
var actions = post["actions"] as JArray; // if this works then all is well
foreach(var item in actions)
{
actionLinks.Add((string)item["link"]);
}
I think you can also use some fancy Linq with this like
var actionLinks = ((JArray)post["actions"])
.Children<JObject>()
.Select(a => (string)a["link"])
.ToList();
Very un-tested. Just let me know.

JSON nested array

Lets say i have the following JSON
{
"data": [
{
"from": {
"name": "aaa bbb",
},
"actions": [
{
"name": "Comment",
"link": "http://...
},
{
"name": "Like",
"link": "http://.."
}
],
},
And i have
JSONObject wallData = helper.Get("/me/feed");
if (wallData != null)
{
var data = wallData.Dictionary["data"];
List<JSONObject> wallPosts = data.Array.ToList<JSONObject>();
}
foreach (Facebook.JSONObject wallItem in wallPosts)
{ ... }
Which stores me whole feed into wallData and 'data' object into wallPosts.
So then i can access the wallItem.Dictionary["from"].Dictionary["name"], and i get "aaa bbb".
But i can't get inside the actions array
The wallItem.Dictionary["actions"].Dictionary["name"] doesn't work.
Any idea
You need to do something like wallItem.Dictionary["actions"][0].Dictionary["name"] because "actions" is an array.
On a different note...its neater if u directly into a class...like this
var jSerializer = new JavaScriptSerializer();
var jsonObject = jSerializer.Deserialize<DataObject>(json);
The DataObject will be a class which emulates ur JSON data in a strongly typed class. Depending on the size of ur Json you will not have to use a lot of strings in your code.

Categories

Resources