Mongo DB update operation - mongodb

Below query wrongly update by mongoDB
Query:
d.update({'Objects.out.interface': 'down', 'IP': '192.168.106.11', 'INID': 19, 'SESSION': 1, 'Objects.id': 4}, {$set: {'Objects.$.score':888888}})
Why my score 888888 updated in Objects.id:2 not in Objects.id:4 ?
Update result:
{
"_id" : ObjectId("59b7ebec9315080ac2801468"),
"SESSION" : 1,
"INID" : 19,
"IP" : "192.168.106.11",
"Hostname" : "Npppp",
"JOBNAME" : "Nexus2-12-September-19-45-08",
"Authentication" : "{\"username\":\"gowtham\",\"password\":\"pppppp\"}",
"Objects" : [
{
"name" : "self",
"out" : {
"status" : "reachable"
},
"type" : "self_check",
"id" : 1,
"rank" : [
{
"regex" : {
"status" : "down"
},
"score" : 0
},
{
"regex" : {
"status" : "reachable"
},
"score" : 100
}
],
"monitor" : "self",
"score" : 100
},
{
"name" : "Eth1/1",
"out" : {
"interface" : "down"
},
"type" : "cis_sw_int",
"id" : 2,
"rank" : [
{
"regex" : {
"interface" : "down"
},
"score" : 0
},
{
"regex" : {
"interface" : "up"
},
"score" : 100
}
],
"monitor" : "bits,duplex,speed,error",
"score" : 888888
},
{
"name" : "Eth1/37",
"out" : {
"interface" : "down"
},
"type" : "cis_sw_int",
"id" : 3,
"rank" : [
{
"regex" : {
"interface" : "down"
},
"score" : 0
},
{
"regex" : {
"interface" : "up"
},
"score" : 100
}
],
"monitor" : "bits,duplex,speed,error"
},
{
"name" : "Eth1/46",
"out" : {
"interface" : "down"
},
"type" : "cis_sw_int",
"id" : 4,
"rank" : [
{
"regex" : {
"interface" : "down"
},
"score" : 0
},
{
"regex" : {
"interface" : "up"
},
"score" : 100
}
],
"monitor" : "bits,duplex,speed,error"
}
],
"timeout" : 10,
"TD" : ISODate("2017-09-12T19:45:08.743Z")
}

Because you have 2 conditions for subdocuments:
'Objects.out.interface': 'down',
'Objects.id': 4
Positional operator uses first matching sub-document
the positional $ operator acts as a placeholder for the first element that matches the query document,
In your case the first match for 'Objects.out.interface': 'down' is the one with id:2.
You need to change the filter to use $elemMatch to use both conditions to identify the subdocument:
{
'IP': '192.168.106.11',
'INID': 19,
'SESSION': 1,
'Objects': {
$elemMatch: {
'out.interface': 'down',
'id': 4
}
}
}

Related

MongoDB - how to optimise find query with regex search, with sort

I need to execute the following query:
db.S12_RU.find({"venue.raw":a,"title":/b|c|d|e/}).sort({"year":-1}).skip(X).limit(Y);
where X and Y are numbers.
The number of documents in my collection is:
208915369
Currently, this sort of query takes about 6 minutes to execute.
I have the following indexes:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"venue.raw" : 1
},
"name" : "venue.raw_1"
},
{
"v" : 2,
"key" : {
"venue.raw" : 1,
"title" : 1,
"year" : -1
},
"name" : "venue.raw_1_title_1_year_-1"
}
]
A standard document looks like this:
{ "_id" : ObjectId("5fc25fc091e3146fb10484af"), "id" : "1967181478", "title" : "Quality of Life of Swedish Women with Fibromyalgia Syndrome, Rheumatoid Arthritis or Systemic Lupus Erythematosus", "authors" : [ { "name" : "Carol S. Burckhardt", "id" : "2052326732" }, { "name" : "Birgitha Archenholtz", "id" : "2800742121" }, { "name" : "Kaisa Mannerkorpi", "id" : "240289002" }, { "name" : "Anders Bjelle", "id" : "2419758571" } ], "venue" : { "raw" : "Journal of Musculoskeletal Pain", "id" : "49327845" }, "year" : 1993, "n_citation" : 31, "page_start" : "199", "page_end" : "207", "doc_type" : "Journal", "publisher" : "Taylor & Francis", "volume" : "1", "issue" : "", "doi" : "10.1300/J094v01n03_20" }
Is there any way to make this query execute in a few seconds?

Mongodb update nested array by id

I have the following document and want to update state
Document ID: ObjectId("5a4e5a448b70d50e34d204a5")
Target ID: ObjectId("5a4e5a438b70d50e34d203ea")
I have no idea how to update the state to e.g. 4
{
"_id" : ObjectId("5a4e5a448b70d50e34d204a5"),
"name" : "Wirtschaftsdienst",
"date" : ISODate("2012-10-07T00:00:00.000Z"),
"comment" : null,
"tasks" : [
{
"name" : "Speisen und Getränke",
"sections" : [
{
"start" : 46800,
"end" : 72000,
"entirely" : true,
"assistants" : [
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203ea")
},
"state" : 3
},
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203f4")
},
"state" : 3
}
]
}
]
}
]
}
Use positional operator $[] along with arrayFilters to get your job done!
Try this query:
db.collection.update(
{"_id" : ObjectId("5a4e5a448b70d50e34d204a5")},
{$set: {"tasks.$[].sections.$[].assistants.$[element].state":4}},
{arrayFilters: [ {"element.assistant":{"_id" :
ObjectId("5a4e5a438b70d50e34d203ea")} }
], multi:true}
)
And the output is:
/* 1 */
{
"_id" : ObjectId("5a4e5a448b70d50e34d204a5"),
"name" : "Wirtschaftsdienst",
"date" : ISODate("2012-10-07T00:00:00.000Z"),
"comment" : null,
"tasks" : [
{
"name" : "Speisen und Getränke",
"sections" : [
{
"start" : 46800,
"end" : 72000,
"entirely" : true,
"assistants" : [
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203ea")
},
"state" : 4.0
},
{
"assistant" : {
"_id" : ObjectId("5a4e5a438b70d50e34d203f4")
},
"state" : 3.0
}
]
}
]
}
]
}

Get data with not,and

MongoDB get data with not,and How to get value for INID not equal to 1 and SESSION not equal to 1 ( need to match INID and SESSION in same document ).
Ex:
{
"_id" : ObjectId("5946800b962d74070729407a"),
"INID" : 2,
"SESSION" : 1,
"TD" : ISODate("2017-06-18T13:28:43.409Z"),
"ID" : 2,
"OUT" : [
{
"score" : 50,
"id" : "0",
"out" : {
"status" : "unreachable"
}
}
]
}
{
"_id" : ObjectId("5946800b962d74070729407a"),
"INID" : 3,
"SESSION" : 1,
"TD" : ISODate("2017-06-18T13:28:43.409Z"),
"ID" : 2,
"OUT" : [
{
"score" : 50,
"id" : "0",
"out" : {
"status" : "unreachable"
}
}
]
}
{
"_id" : ObjectId("5946800b962d74070729407a"),
"INID" : 1,
"SESSION" : 1,
"TD" : ISODate("2017-06-18T13:28:43.409Z"),
"ID" : 2,
"OUT" : [
{
"score" : 50,
"id" : "0",
"out" : {
"status" : "unreachable"
}
}
]
}
I want the first two documents.
Well, this worked for me:
db.yourCollectionName.find(
{ $or : [ { INID : {$gt: 1} }, { SESSION : {$gt: 1} } ] }
)
With this query you can have INID larger than 1 or SESSION larger than 1 or both larger than one. Why would you need to negate?
I guess you can also do this:
db.yourCollectionName.find(
{ $or : [ { INID : {$ne: 1} }, { SESSION : {$ne: 1} } ] }
)

Only return inner element from nested array in Mongo

I currently have a collection that contains documents like this
{
"_id" : "sHXFGyTkZBYeZXcax",
"name" : "Sunless Sunday",
"description" : "blabla",
"game_id" : "qPrZBahQLHQXabwuv",
"date_checkin" : ISODate("2015-11-07T01:01:00.000Z"),
"date_start" : ISODate("2015-11-12T00:04:00.000Z"),
"date_end" : ISODate("2015-11-19T00:05:00.000Z"),
"company_id" : 1,
"featured" : 1,
"premium" : 0,
"type" : 0,
"ongoing" : 1,
"prizes" : [
{
"place" : 1,
"amount" : 18
},
{
"place" : 2,
"amount" : 2
}
],
"createdAt" : ISODate("2015-11-05T22:34:01.494Z"),
"modifiedAt" : ISODate("2015-11-05T22:34:01.494Z"),
"owner" : "CLEopD9HRAeE9eiXW",
"players" : [
{
"player_id" : "WdLK9aaRgdPnYsw8B",
"status" : 2
},
{
"player_id" : "vF6JEwMy9yaRtKuiG",
"status" : 1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : -1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : 1
}
],
"rounds" : [
{
"roundNumber" : 1,
"participants" : [],
"matchesToWin" : 3,
"matches" : [
{
"matchNumber" : 1,
"party1" : "WdLK9aaRgdPnYsw8B"
}
]
},
{
"roundNumber" : 2,
"participants" : [
{
"player_id" : "WdLK9aaRgdPnYsw8B",
"status" : 2
},
{
"player_id" : "vF6JEwMy9yaRtKuiG",
"status" : 1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"status" : 1
}
],
"matchesToWin" : 2,
"matches" : [
{
"matchNumber" : 1,
"players" : [
{
"party" : 1
},
{
"player_id" : "WdLK9aaRgdPnYsw8B",
"party" : 2
}
],
"party1" : "freewin",
"party2" : "WdLK9aaRgdPnYsw8B",
"currentGame" : 1,
"winner" : "WdLK9aaRgdPnYsw8B",
"matchFinished" : ISODate("2015-11-16T16:25:37.712Z")
},
{
"matchNumber" : 2,
"players" : [
{
"player_id" : "vF6JEwMy9yaRtKuiG",
"party" : 1
},
{
"player_id" : "KD4s2E3AezhFcQDCd",
"party" : 2
}
],
"party1" : "vF6JEwMy9yaRtKuiG",
"party2" : "KD4s2E3AezhFcQDCd",
"score1" : 0,
"score2" : 0,
"currentGame" : 1
}
]
}
]
}
Now I'm trying to see if a certain player has an active match. So this means that the the player would be either party1 or party2 in a match that has no winner at the moment.
I currently have this query
activeMatch = Tournaments.find({
'ongoing': 1,
'rounds.matches': {
$elemMatch: {
$or: [
{ 'party1': player[0]._id },
{ 'party2': player[0]._id },
],
winner: { $exists: false }
}
}
},
{ "rounds.matches.$": 1 }
);
I have 2 problems at the moment:
My query returns the round it matched, but it does not filter for the match it matched. So I effectively only get round with roundNumber = 2, but from that round I get every match, where as I would only be interested in a specific match.
The filtering only happens when I execute my query through the shell. When I use it in my .jsx file and console.log the result to the client, I see ALL rounds.
Any help?

Nested conditional MongoDB query

Im having a hard time trying to run some nested queries with a conditional statement of an item inside an array.
this is how my documents looks like.
I would like to get a summary such as sum and average and alarmedCount (count every time Channels.AlarmStatus == "alarmed") of each "Channel" based on Channels.Id. I got sum and average to work but cant get the right query for alarmedCount
{
"_id" : "55df8e4cd8afa4ccer1915ee"
"location" : "1",
"Channels" : [{
"_id" : "55df8e4cdsafa4cc0d1915r1",
"ChannelId" : 1,
"Value" : 14,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915r9",
"ChannelId" : 2,
"Value" : 20,
"AlarmStatus" : "alarmed"
},
{
"_id" : "55df8e4cdsafa4cc0d1915re",
"ChannelId" : 3,
"Value" : 10,
"AlarmStatus" : "alarmed"},
]
}
{
"_id" : "55df8e4cd8afa4ccer1915e0"
"location" : "1",
"Channels" : [{
"_id" : "55df8e4cdsafa4cc0d19159",
"ChannelId" : 1,
"Value" : 50,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915re",
"ChannelId" : 2,
"Value" : 16,
"AlarmStatus" : "normal"
},
{
"_id" : "55df8e4cdsafa4cc0d1915g7",
"ChannelId" : 3,
"Value" : 9,
"AlarmStatus" : "alarmed"},
]
}
I got it to work to group them and show some calculations
using this aggregate
db.records.aggregate( [
{
"$unwind" : "$Channels"
},
{
"$group" : {
"_id" : "$Channels.Id",
"documentSum" : { "$sum" : "$Channels.Value" },
"documentAvg" : { "$avg" : "$Channels.Value" }
}
}
] )
the result looks like this:
{
"result" : [
{
"_id" : 1,
"documentSum" : 64,
"documentAvg" : 32
},
{
"_id" : 2,
"documentSum" : 36,
"documentAvg" : 18
},
{
"_id" : 3,
"documentSum" : 19,
"documentAvg" : 9.5
},
],
"ok" : 1.0000000000000000
}
I would like to get this type of result
{
"result" : [
{
"_id" : 1,
"documentSum" : 64,
"documentAvg" : 32,
"AlarmedCount" : 0
},
{
"_id" : 2,
"documentSum" : 36,
"documentAvg" : 18,
"AlarmedCount" : 1
},
{
"_id" : 3,
"documentSum" : 19,
"documentAvg" : 9.5,
"AlarmedCount" : 2
}
],
"ok" : 1.0000000000000000
}
Use a project-step before your group-step to convert the field AlarmedStatus to 1 or 0 depending on its value:
$project: {
"Channels.value":"$Channels.Value",
"Channels.AlarmCount":{ $cond: {
if: { $eq: ["$Channels.AlarmedStatus", "alarmed"] },
then: 1,
else: 0 }
}
}
Then sum the newly created field to get the aggregated count:
$group : {
"_id" : "$Channels.Id",
"documentSum" : { "$sum" : "$Channels.Value" },
"documentAvg" : { "$avg" : "$Channels.Value" },
"AlarmCount" : { "$sum" : "$Channels.AlarmCount" }
}