Select entries which doesn't have specified key - mongodb

Assume, that I have bunch of entries in a document:
db.document
and some of them doesn't have some key, let's say name. So we have two types of entries - with and without name.
{ "_id" : ObjectId("4dea81a8bd2bb0323800002d"), "fetched_at" : ISODate("2013-08-02T17:41:30Z"), "keyword" : "110770", "name" : "SOME NAME" }
{ "_id" : ObjectId("4dea81a8bd2bb0323800002a"), "fetched_at" : ISODate("2013-08-02T17:44:17Z"), "keyword" : "125176" }
I want to remove all entries without name property, because it makes my database incosistent. How can I do that? I tried with null and undefined but it doesn't works.

it's possible using $exists:
db.document.remove( { name : { $exists : false } } );

db.document.remove( { name : null } )
should work too. Example:
> db.document.insert({"fetched_at" : ISODate("2013-08-02T17:41:30Z"), "keyword" : "110770", "name" : "SOME NAME"})
> db.document.insert({"fetched_at" : ISODate("2013-08-02T17:44:17Z"), "keyword" : "125176" })
> db.document.insert({"fetched_at" : ISODate("2013-08-02T17:44:17Z"), "keyword" : "125176" })
> db.document.find().size()
3
> db.document.remove({name:null})
> db.document.find().size()
1
> db.document.find().pretty()
{
"_id" : ObjectId("520eac7e5d0ee1aa8515a550"),
"fetched_at" : ISODate("2013-08-02T17:41:30Z"),
"keyword" : "110770",
"name" : "SOME NAME"
}

Related

Mongodb put Documents array as the same level

I have this array of documents, I would like to put "table" on the same level like mastil_antenas and other variables. how Can I do that with aggregate?
I'm trying with the aggregate $project but I can't get the result.
Example of Data
[ {
"mastil_antena" : "1",
"nro_platf" : "1",
"antmarcmast" : "ANDREW",
"antmodelmast" : "HWXXX6516DSA3M",
"retmarcmast" : "Ericsson",
"retmodelmast" : "ATM200-A20",
"distmast" : "1.50",
"altncramast" : "41.30",
"ORIENTMAG" : "73.00",
"incelecmast" : "RET",
"incmecmast" : "1.00",
"Feedertypemast" : "Fibra Optica",
"longjumpmast" : "5.00",
"longfo" : "100",
"calibrecablefuerza" : "10 mm",
"longcablefuerza" : "65.00",
"modelorruantena" : "32B66A",
"tiltmecfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114934746000.jpg",
"tiltmecfoto_fh" : "2017-10-18T05:51:22Z",
"az0foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115012727000.jpg",
"az0foto_fh" : "2017-10-18T05:55:21Z",
"azneg60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115016199000.jpg",
"azneg60foto_fh" : "2017-10-18T05:55:36Z",
"azpos60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115020147000.jpg",
"azpos60foto_fh" : "2017-10-18T05:55:49Z",
"etiqantenafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114920853000.jpg",
"etiqantenafoto_fh" : "2017-10-18T05:56:01Z",
"tiltelectfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114914236000.jpg",
"tiltelectfoto_fh" : "2017-10-18T05:56:13Z",
"idcablefoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114900279000.jpg",
"idcablefoto_fh" : "2017-10-18T05:56:38Z",
"rrutmafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114947279000.jpg",
"rrutmafoto_fh" : "2017-10-18T05:56:49Z",
"etiquetarrufoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114954648000.jpg",
"etiquetarrufoto_fh" : "2017-10-18T05:57:02Z",
"rrutmafoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114959738000.jpg",
"rrutmafoto1_fh" : "2017-10-18T05:57:12Z",
"etiquetarrufoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115005545000.jpg",
"etiquetarrufoto1_fh" : "2017-10-18T05:57:27Z",
"botontorre4" : "sstelcel3",
"table" : { /* put all varibles one level up*/
"tecmast" : "LTE",
"frecmast" : "2100",
"secmast" : "1",
"untitled440" : "Salir"
},
"comentmast" : "",
"longfeedmast" : "",
"numtmasmast" : "",
"otra_marca_antena" : "",
"otro_modelo_antena" : ""
}]
Starting from MongoDB version 3.4 you could use $addFields to do this.
//replace products with what makes sense in your database
db.getCollection('products').aggregate(
[
{ //1 add the properties from subdocument table to documents
$addFields: {
"documents.tecmast" : "documents.0.table.tecmast",
"documents.frecmast" : "documents.0.table.frecmast",
"documents.secmast" : "documents.0.table.secmast",
"documents.untitled440" : "documents.0.table.untitled440"
}
},
{
//(optional) 2 remove the table property from the documents
$project: {"documents.table" : 0}
}
]
)
Step 1: use $addFields to grab properties from table inside documents.table and put them on documents
Step 2: (optional) remove property "table" from documents.
I hope this helps!!!

How to find something from an array in mongo

{
"_id" : ObjectId("586aac4c8231ee0b98458045"),
"store_code" : NumberInt(10800),
"counter_name" : "R.N.Electric",
"address" : "314 khatipura road",
"locality" : "Khatipura Road (Jhotwara)",
"pincode" : NumberInt(302012),
"town" : "JAIPUR",
"gtm_city" : "JAIPUR",
"sales_office" : "URAJ",
"owner_name" : "Rajeev",
"owner_mobile" : "9828024073",
"division_mapping" : [//this contains only 1 element in every doc
{
"dvcode" : "cfc",
"dc" : "trade",
"beatcode" : "govindpura",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ", //office
"gtm_city" : "JAIPUR" //city
},
"beat" : {
"_id" : ObjectId("586d372b39f64316b9c3cbd7"),
"division" : {
"_id" : ObjectId("5869f8b639f6430fe4edee2a"),
"clientdvcode" : NumberInt(40),
"code" : "cfc",
"name" : "Cooking & Fabric Care",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global"
},
"beatcode" : "govindpura",
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR",
"active" : true,
"agency_code" : "v5global",
"client_code" : "USHA_FOS",
"proj_code" : "usha-fos",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR"
}
}
}
],
"distributor_mail" : "sunil.todi#yahoo.in",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global",
"distributor_name" : "Sundeep Electrical"
}
I am having only 1 element in division_mapping's array and I want to find those documents whose dc in division_mapping is trade.
I have tried following:
"division_mapping":{$elemMatch:{$eq:{"dc":"trade"}}}})
Dont know what I am doing wrong.
//Maybe I have to unwind the array but is there any other way?
According to MongoDB documentation
The $elemMatch operator matches documents that contain an array
field with at least one element that matches all the specified query
criteria.
According to above mentioned description to retrieve only documents whose dc in division_mapping is trade please try executing below mentioned query
db.collection.find({division_mapping:{$elemMatch:{dc:'trade'}}})

In mongodb is it possible to query by sub-object?

I have an doc in mongo:
{
"_id" : ObjectId("54eb5189ad9685bbb622ca52"),
"header" : {
"title" : "Project Name 1",
"header_img" : "project_name_1.png",
"project_stats" : {
"sqFt" : 20000,
"tons" : 300,
"duration" : "6 months",
"type" : "education facility",
"summary" : "Give quick summary of problem solved."
}
},
"row_project_detail" : {
"project_logo" : "project_name_1_logo.png",
"header" : "Project Name 1 was a project where...",
"paragraph" : "blah blah blah blah"
},
"row_1" : {
"img" : "project_name_2.png"
},
"row_2" : {
"img_1" : "project_name_3.png",
"img_2" : "project_name_4.png"
},
"row_3" : {
"img" : "project_name_5.png"
},
"row_4" : {
"img" : "project_name_6.png"
}
}
I have tried to query by db.projects.find({ header: { title: "Project Name 1"} }); but it does not produce results. How can I query by the title key in the header object? Is this possible or do I simply need to duplicate the title key from the header sub-object and put that at the root of the doc?
Use dot notation:
db.projects.find({ "header.title": "Project Name 1"});

How to update particular array element in MongoDB

I am newbie in MongoDB. I have stored data inside mongoDB in below format
"_id" : ObjectId("51d5725c7be2c20819ac8a22"),
"chrom" : "chr22",
"pos" : 17060409,
"information" : [
{
"name" : "Category",
"value" : "3"
},
{
"name" : "INDEL",
"value" : "INDEL"
},
{
"name" : "DP",
"value" : "31"
},
{
"name" : "FORMAT",
"value" : "GT:PL:GQ"
},
{
"name" : "PV4",
"value" : "1,0.21,0.00096,1"
}
],
"sampleID" : "Job1373964150558382243283"
I want to update the value to 11 which has the name as Category.
I have tried below query:
db.VariantEntries.update({$and:[ { "pos" : 117199533} , { "sampleID" : "Job1373964150558382243283"},{"information.name":"Category"}]},{$set:{'information.value':'11'}})
but Mongo replies
can't append to array using string field name [value]
How one can form a query which will update the particular value?
You can use the $ positional operator to identify the first array element to match the query in the update like this:
db.VariantEntries.update({
"pos": 17060409,
"sampleID": "Job1373964150558382243283",
"information.name":"Category"
},{
$set:{'information.$.value':'11'}
})
In MongoDB you can't adress array values this way. So you should change your schema design to:
"information" : {
'category' : 3,
'INDEL' : INDEL
...
}
Then you can adress the single fields in your query:
db.VariantEntries.update(
{
{"pos" : 117199533} ,
{"sampleID" : "Job1373964150558382243283"},
{"information.category":3}
},
{
$set:{'information.category':'11'}
}
)

MongoDB aggregation to return nested groups with values as keys?

My documents look like this:
{
"_id" : "Tvq579754r",
"Status" : "passed",
"Title" : "up08c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 11114.85,
"METRIC_B" : 68.9,
"METRIC_C" : 65.35,
},
{
"_id" : "Tvq579755r",
"Status" : "passed",
"Title" : "up09c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 21114.85,
"METRIC_B" : 168.9,
"METRIC_C" : 165.35,
},
{
"_id" : "Tvq579756r",
"Status" : "passed",
"Title" : "up09c",
"ProjectID" : "Tvq5p",
"Version" : "1.0.0",
"Platform" : "platform_x",
"METRIC_A" : 31114.85,
"METRIC_B" : 268.9,
"METRIC_C" : 265.35,
}
Now I have no problem grouping and getting $avg and $sum of my METRIC_ fields by grouping by ProjectID, Version, Platform and Title, but what I'd like to do within the aggregation framework (if possible) is to return an object that uses the grouped values as keys, such as:
{
<Project ID> : {
<Version> : {
<Platform> : {
<Title> : {
"METRIC_A": <sum of METRIC_A>,
"METRIC_B": <sum of METRIC_B>,
"METRIC_C": <sum of METRIC_C>,
}
}
}
}
}
Or, in context of my example:
{
'Tvq5p' : {
'1.0.0' : {
'platform_x' : {
'up08c' : {
"METRIC_A": 11114.85,
"METRIC_B": 68.9,
"METRIC_C": 65.35,
},
'up09c' : {
"METRIC_A": 52229.7,
"METRIC_B": 437.8,
"METRIC_C": 430.7,
}
}
}
}
}
I am currently doing it once the query results are received by the consuming service, which isn't terribly slow or anything, but I just thought it would be nice to come that way right out of Mongo. Is this even possible?
Thanks.
In MongoDB there is the group operation.
db.records.group( {
key: { 'platform_x': 1, 'title': 1 },
reduce: function(cur, result) {
result.metric_a += cur.metric_a;
result.metric_b += cur.metric_b;
result.metric_c += cur.metric_c;
},
initial: { metric_a = 0, metric_b = 0, metric_c = 0 }
} )
If that doesn't work I'd recommend a Map Reduce.