How to find number of distinct fields in a collection in mongodb - c#

As MongoDB provides the flexibility to store the unstructured data,
Is there any way in mongodb C# driver, I can find the number of distinct fields name from a collection.
I mean to say
{
"_id" : ObjectId("52fb69ff1ecf0322f0ab3129"),
"Serial Number" : "1",
"Name" : "Sameer Singh Rathoud",
"Skill" : "C++",
"City" : "Pune",
"Country" : "India"
}
{
"_id" : ObjectId("52fb69ff1ecf0322f0ab312a"),
"Serial Number" : "2",
"Name" : "Prashant Patil",
"DOB" : "31/07/1978",
"Location" : "Hinjewadi",
"State" : "Maharashtra",
"Country" : "India"
}
I want to get [_id, Serial Number, Name, DOB, Skill, City, State, Country]

i also faced this issue. If you till not got proper solution or for new person who searching solution for this kind of question they can use this.
var keys = [];
db.Entity.find().forEach(function(doc){
for (var key in doc){
if(keys.indexOf(key) < 0){
keys.push(key);
}
}
});
print(keys);

Related

Dynamically Query a Mongo Collection in c#

I'm new to C# mongo,earlier worked on Node and Mongo.
i have a collection called tasks.Below is a sample record.
{
"_id" : ObjectId("6193bfba23855443a127466a"),
"taskIdentifier" : LUUID("00000000-0000-0000-0000-000000000000"),
"title" : "PR Liquidators",
"company" : "iuytreugdfh",
"purpose" : "test purpose",
"column" : "Search",
"assignTo" : "Shiva",
"assignToId" : ObjectId("61933b47a79ac615648a7855"),
"assignToImage" : null,
"notes" : "ggh#William james ",
"done" : 0,
"taskID" : "00029",
"status" : "Pending",
"states" : [
"Alabama - AL",
"Alaska - AK"
],
"active" : true,
"updatedAtUtc" : ISODate("2021-11-18T12:26:37.616Z"),
"updatedBy" : ""
}
in my c# webapi Project i always get a array called filterCriteria from api request of below form:
filterCriteria=[
{key:"purpose",value:"test purpose",type:"eq"},
{key:"active",value:true,type:"eq"}
]
Now I want to query the mongo collection tasks using the given filterCriteria.
tried something using LINQ statements but no use --hardcoding works but dynamically not working.
How can I achieve this???
maybe you are looking for Builders:
public enum FilterType{
eq=1,//equal
gt=2//greater than
}
//************
var builder = Builders<FilterCritertiaModel>.Filter;
var query = builder.Empty;
foreach(var filterCriteriaItem in filterCriteria){
switch (filterCriteriaItem.type) {
case eq:
query &= builder.Eq(filterCriteriaItem.Key, filterCriteriaItem.Value);
case gt:
query &=builder.Gt(filterCriteriaItem.Key, filterCriteriaItem.Value);
//all cases....
}

C# MongoDB index causes weird duplicate exceptions

we have a problem with our indexes. We have an index on our emails but it throws errors like such:
> db.User.insert({email: "hell33o#gmail.com", "_id" : BinData(3,"iKyq6FvBCdd54TdxxX0JhA==")})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: placetobe.User.$email_text dup key: { : \"com\", : 0.6666666666666666 }"
}
})
when we have the index created with our C# driver like this
Created by C# with:
CreateIndexOptions options = new CreateIndexOptions {Unique = true};
_collection.Indexes.CreateOneAsync(Builders<User>.IndexKeys.Text(_ => _.email), options);
resulted in
{
"v" : 1,
"unique" : true,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "email_text",
"ns" : "placetobe.User",
"weights" : {
"email" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 2
}
but if we create it with the MongoDB console like this it works:
{
"v" : 1,
"unique" : true,
"key" : {
"email" : 1
},
"name" : "email_1",
"ns" : "placetobe.User"
}
I don't understand the difference between the two indexes, but they have an effect on our DB. We also have problems with a Collectin that saves names. we get duplicate exceptions on "Molly" if we try to insert "Molli". With the emails is seems to give us errors whenever we have two "gmail" emails in the collection or two ".com" emails etc.
This is a University project and we have to turn it in tomorrow. we're really in trouble, help would be much appreciated
You don't want your email to be a text Index. Text indices allow you to search large amounts of text in MongoDB like if you were parsing through comments or something. All you want is to make sure your emails aren't duplicated so you should use an ascending or descending index.
CreateIndexOptions options = new CreateIndexOptions {Unique = true};
_collection.Indexes.CreateOneAsync(Builders<User>.IndexKeys.Ascending(_ => _.email), options)

Updating Embedded Array MongoDB/C#

I have an interesting scenario where I have a 2-level embedded array in a Mongo Document and I can't seem to figure out a way to update elements inside the 2nd level. I've tried ElemMatch but it doesn't seem to be working.
I have a Product document which has an Attributes array. This Attributes Array has multiple options. Ex. a Product could be a t-shirt, with attributes Size, Color. Each Attribute could have options. For e.g. Size has options XS, S, M, L. Now I want the ability to update the size option given the OptionId (and/or the Attribute Id).
Here's how my Mongo document looks like:
{
"Attributes" : [{
"_id" : ObjectId("52adf86912a4590a3cb322a5"),
"Name" : "Size",
"LabelText" : "Select your T-Shirt Size",
"Description" : "This is the Size of the T-Shirt",
"ShowOnDisplay" : true,
"Options" : [{
"_id" : ObjectId("52adf86912a4590a3cb322a6"),
"Name" : "XS",
"Value" : "XS"
}, {
"_id" : ObjectId("52adf86912a4590a3cb322a7"),
"Name" : "S",
"Value" : "S"
}],
"DateCreatedUtc" : new Date("12/15/2013 10:43:53"),
"DateModifiedUtc" : new Date("12/15/2013 10:43:53")
}],
"AvailableEndTimeUtc" : null,
"AvailableStartTimeUtc" : null,
"Name" : "CMR Dazzle T-Shirt ",
"Price" : {
"Value" : "25",
"Currency" : "USD"
},
"Sku" : "SKU7fb3a",
"_id" : ObjectId("52adf86912a4590a3cb322a4")
}
In the example above, I'd like to update the XS to say "X-Small". I have both the Attribute Id and the Option Id available.
I've tried using ElemMatch, I've tried simple Query.EQ("Attributes.Options._id") and then used update and nothing works. Similar to that, I'd also like to delete an option given an id.
I would greatly appreciate any help here.
I think what you want to do is the same as being discussed here. This is currently not possible in Mongo, see this JIRA.

Summing large amounts of data on mongodb

Im looking for the most efficient way of performing summing queries against mongodb.
Currently we insert documents that contain various information and a date time stamp of when the document was created.
We need to sum this data to be viewed in the following ways:
Documents by hour of the day 1-24
Documents by day of the month 1-28/31
Documents by month of the year 1-12
Documents by year
This summed data will be accessed often as we're afraid that the massive amount of data thrown at mongo will have problems summing this data often.
We thought perhaps when a document is inserted into mongo that we have another document that contains these counts that we increment at the time of insertion. This way, we can quickly pull the counts without summing the data each request. Our concern is that this may not be the most efficient way to perform this type of operation in mongo
Any thoughts on the best way to accomplish this? My dev team as well as myself are new to mongodb and we want to make sure we don't fall into a performance trap with summing large sets of data.
The Aggregation Framework is perfectly suited for this type of queries.
I've done some examples for you below.
To start, let's populate some documents:
db.myDocumentCollection.insert({"date" : new Date('01/01/2012'),
"topic" : "My Title 1"}); db.myDocumentCollection.insert({"date" : new
Date('01/02/2012'), "topic" : "My Title 2"});
db.myDocumentCollection.insert({"date" : new Date('01/02/2012'),
"topic" : "My Title 3"}); db.myDocumentCollection.insert({"date" : new
Date('01/02/2012'), "topic" : "My Title 4"});
db.myDocumentCollection.insert({"date" : new Date('01/04/2012'),
"topic" : "My Title 5"}); db.myDocumentCollection.insert({"date" : new
Date('01/05/2012'), "topic" : "My Title 6"});
db.myDocumentCollection.insert({"date" : new Date('01/07/2013'),
"topic" : "My Title 7"}); db.myDocumentCollection.insert({"date" : new
Date('01/07/2013'), "topic" : "My Title 8"});
db.myDocumentCollection.insert({"date" : new Date('02/07/2013'),
"topic" : "My Title 9"}); db.myDocumentCollection.insert({"date" : new
Date('02/08/2013'), "topic" : "My Title 10"});
Return number of documents grouped by full date
db.myDocumentCollection.group(
{
$keyf : function(doc) {
return { "date" : doc.date.getDate()+"/"+doc.date.getMonth()+"/"+doc.date.getFullYear() };
},
initial: {count:0},
reduce: function(obj, prev) { prev.count++; }
})
Output
[
{
"date" : "1/0/2012",
"count" : 1
},
{
"date" : "2/0/2012",
"count" : 3
},
{
"date" : "4/0/2012",
"count" : 1
},
{
"date" : "5/0/2012",
"count" : 1
},
{
"date" : "7/0/2013",
"count" : 2
},
{
"date" : "7/1/2013",
"count" : 1
},
{
"date" : "8/1/2013",
"count" : 1
}
]
Return number of documents grouped by day of month for the year 2013
This is perhaps a little more relevant for the kinds of queries you want to do.
Here, we use the cond to specify only to group documents after 1/1/2013
You could use $gte and $lte to do date ranges here.
db.myDocumentCollection.group(
{
$keyf : function(doc) {
return { "date" : doc.date.getDate()+"/"+doc.date.getMonth()};
},
cond: {"date" : {"$gte": new Date('01/01/2013')}},
initial: {count:0},
reduce: function(obj, prev) { prev.count++; }
})
Output
[
{
"date" : "7/0",
"count" : 2
},
{
"date" : "7/1",
"count" : 1
},
{
"date" : "8/1",
"count" : 1
}
]

Compare the field values in MongoDB

i have two collection A and B
for A contains
{
"_id" : ObjectId("4fb2143af31dfd122ce39c4b"),
"Name" : "Freelander 2.2D",
"Manufacture" : "Landrover"
}
and B ,
{
"_id" : ObjectId("4fb21439f31dfd122ce39c4a")
"Name" : "Rangerover",
"Manufacture" : "Landrover",
}
let me know how to check field values same(here it is "Name" have different values) for A and B in C# driver .If it finds differences i need to update too
Please shed some light on this,Thanks in advance
You can't do queries that involve more than one collection. One query - one collection, period.
Well, Sergio is mostly right (I can't see a way to do this using a language driver), but it is possible using the shell:
var a_in_b = function(o){
var numB = db.B.find({Name:o.Name}).count();
if (numB > 0) print (o.Name + " is in both A and B");
}
> db.A.find()
{ "_id" : ObjectId("4fb2143af31dfd122ce39c4b"), "Name" : "Freelander 2.2D", "Manufacture" : "Landrover" }
> db.B.find()
{ "_id" : ObjectId("4fb667d60569d84fec6ef57e"), "Name" : "Rangerover", "Manufacture" : "Landrover" }
{ "_id" : ObjectId("4fb66a830569d84fec6ef57f"), "Name" : "Freelander 2.2D", "Manufacture" : "Landrover" }
> db.A.find().forEach(a_in_b);
Freelander 2.2D is in both A and B
If your requirement is an admin-related one, this might be what you're looking for. If you're wanting to do this from the C# driver (like a SQL join, I guess), then no, you can't.

Categories