How to match field with another field of sub document in Mongo - mysql

mlb_players is a collection having dataId as a field and a teamData as another sub document containing teamId and dataId.
Equivalent MySql: SELECT p.playerId FROM mlb_players p INNER JOIN mlb_teams t ON p.dataId=t.dataId
I want to convert this mysql query into equivalent of mongoDB.
Currently I am using below mongo query but giving an error:
db.getCollection('mlb_players').find({$where: "this.dataId == this.teamData.dataId"});
But it is giving me 0 records however with the same data in mysql is giving my 50 records.
For reference, the 1 of the document looks like:
{
"_id" : ObjectId("55574d05e03ce60f64797432"),
"dataId" : "87c484cc-e672-4a34-ab02-cc29101d8a52",
"teamId" : "TB",
"posId" : "SS",
"playerName" : "Nick Franklin",
"playerNameAbbr" : "N. Franklin",
"playerJersey" : 2,
"playerStatus" : "D",
"playerSalary" : 5500,
"salarySuggest" : 0,
"playerProj" : 0.0,
"playerAvg" : 0.0,
"manualSalary" : 1,
"playerImg" : 0,
"hasImage" : 0,
"used" : 0,
"teamData" : {
"_id" : ObjectId("554239eb4e7235204100002a"),
"teamId" : "TB",
"dataId" : "87c484cc-e672-4a34-ab02-cc29101d8a52",
"teamName" : "Tampa Bay Rays",
"teamAbbr" : "TB"
}
}
Please suggest. Thanks in Advance

You can use aggregation and the $eq operator
db.mlb_players.aggregate(
[
{ $project: { "m": { $eq: [ "$dataId", "$teamData.dataId" ]}}},
{ $match: { "m": true }},
{ $project: { "_id": 1 }}
]
)

In first sentence you wrote that you have players collection, but your query looks for players in mlb_players collection. Maybe that is the purpose of not getting any documents...

Related

Create view with two object array from seperate collections in mongodb

I want to create a view which fields are come from two different object array with seperate collections.For more explanation here is my code
{
"_id" : ObjectId("5e4173cf51af9f555e64531c"),
"__v" : 0,
"createdDate" : ISODate("2020-02-24T08:33:24.100Z"),
"maxDate" : {
"month" : 12,
"year" : 2018
},
"modifiedDate" : ISODate("2020-02-24T08:33:33.025Z"),
"stockArray" : [
{
"purchase_bill_date" : "1/9/2017",
"purchase_bill_series" : "A",
"purchase_bill_item_no" : "419905",
"stock_code" : "5372123-ANN",
},
{
"purchase_bill_date" : "1/9/2017",
"purchase_bill_series" : "A",
"purchase_bill_item_no" : "419905",
"stock_name" : "53743N-10-10S",
}]
}
and the other collection
{
"_id" : ObjectId("5e4173cf51af9f555e64531c"),
"__v" : 0,
"yuklenimReports" : [
{
"purchase_bill_date" : "9/3/2018",
"purchase_bill_series" : null,
"purchase_bill_item_no" : "419905",
""stock_name" : "53743N-10-10S"
}]
}
i want to inner join purchase_bill_item_no and show the others.But i couldnt handle i spent too much hour to find the solution.Thanks for all help.

Mongolite group by/aggregate on JSON object

I have a json document like this on my mongodb collection:
Updated document:
{
"_id" : ObjectId("59da4aef8c5d757027a5a614"),
"input" : "hi",
"output" : "Hi. How can I help you?",
"intent" : "[{\"intent\":\"greeting\",\"confidence\":0.8154089450836182}]",
"entities" : "[]",
"context" : "{\"conversation_id\":\"48181e58-dd51-405a-bb00-c875c01afa0a\",\"system\":{\"dialog_stack\":[{\"dialog_node\":\"root\"}],\"dialog_turn_counter\":1,\"dialog_request_counter\":1,\"_node_output_map\":{\"node_5_1505291032665\":[0]},\"branch_exited\":true,\"branch_exited_reason\":\"completed\"}}",
"user_id" : "50001",
"time_in" : ISODate("2017-10-08T15:57:32.000Z"),
"time_out" : ISODate("2017-10-08T15:57:35.000Z"),
"reaction" : "1"
}
I need to perform group by on intent.intent field and I'm using Rstudio with mongolite library.
What I have tried is :
pp = '[{"$unwind": "$intent"},{"$group":{"_id":"$intent.intent", "count": {"$sum":1} }}]'
stats <- chat$aggregate(
pipeline=pp,
options = '{"allowDiskUse":true}'
)
print(stats)
But it's not working, output for above code is
_id count
1 NA 727
If intent attribute type is string and keep the object as string.
We can split it to array with \" and use third item of array.
db.getCollection('test1').aggregate([
{ "$project": { intent_text : { $arrayElemAt : [ { $split: ["$intent", "\""] } ,3 ] } } },
{ "$group": {"_id": "$intent_text" , "count": {"$sum":1} }}
])
Result:
{
"_id" : "greeting",
"count" : 1.0
}

MongoDB complex select count group by function

I have a collection called 'my_emails' where are stored email addresses :
[
{ email:"russel#gmail.com"},
{ email:"mickey#yahoo.com"},
{ email:"john#yahoo.com"},
]
and I try to get the top 10 hostnames used...
[
{host: "gmail.com", count: 1000},
{host: "yahoo.com", count: 989}, ...
]
if I had MySQL, I’ll do this query :
SELECT substr(email,locate('#',email)+1,255) AS host,count(1) AS count
FROM my_emails
WHERE email like '%#%'
GROUP BY substr(email,locate('#',email)+1,255)
ORDER BY count(1) DESC
LIMIT 10
how can I do with mongodb ?
I try without result something like this :
db.my_emails.aggregate([ { $group : {_id : "$host", count : { $sum : 1 }}}]);
I don't know how to make the $host value without adding a new property to my records
MongoDB doesn't provide any operator like locate but you can use .mapReduce to do this:
db.collection.mapReduce(
function() {
emit(this.email.substr(this.email.indexOf('#') + 1), 1);
},
function(host, count) {
return Array.sum(count) ; },
{ out: "hosts" }
)
Then db.hosts.find().sort({ 'value': -1 }).limit(10) returns top 10 hostname:
{ "_id" : "yahoo.com", "value" : 2 }
{ "_id" : "gmail.com", "value" : 1 }
An alternative workaround would be to modify your data structure by introducing another field in your schema which holds only the domain value of the email address. This can be done with a bulk update using the Bulk API operations that give a better write response i.e. useful information about what actually happened during the update:
var bulk = db.my_emails.initializeUnorderedBulkOp(),
count = 0;
db.my_emails.find().forEach(function(doc) {
var domain = doc.email.replace(/.*#/, ""),
update = { domain: domain };
bulk.find({ "_id": doc._id }).updateOne({
"$set": update
})
count++;
if (count % 1000 == 0) {
bulk.execute();
bulk = db.my_emails.initializeUnorderedBulkOp();
}
})
if (count % 1000 != 0) { bulk.execute(); }
Bulk update response from sample:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})
After this update, a query on the collection db.my_emails.find().pretty() will yield:
{
"_id" : ObjectId("561618af645a64b1a70af2c5"),
"email" : "russel#gmail.com",
"domain" : "gmail.com"
}
{
"_id" : ObjectId("561618af645a64b1a70af2c6"),
"email" : "mickey#yahoo.com",
"domain" : "yahoo.com"
}
{
"_id" : ObjectId("561618af645a64b1a70af2c7"),
"email" : "john#yahoo.com",
"domain" : "yahoo.com"
}
Now, having the domain field will make it easier for the aggregation framework to give you the host count through the $sum operator in the $group pipeline. The following pipeline operation will return the desired outcome:
db.my_emails.aggregate([
{
"$group": {
"_id": "$domain",
"count": { "$sum": 1 }
}
}
])
Output:
{ "_id" : "yahoo.com", "count" : 2 }
{ "_id" : "gmail.com", "count" : 1 }

MongoDB doesnt give the right result

Problem with mongoDB
I have a collection in my mongodb with the following colums:
{"_id" : ObjectId("5443cddc425e215c7290a179"), "orderid" : 1002854, "customerid" : 45978, "campaignid" : 2141, "orderdate" : "2009-10-13 00:00:00", "city" : "NEWTON", "state" : "MA", "zipcode" : 2459, "paymenttype" : "VI", "totalprice" : 190, "numorderlines" : 3, "numunits" : 3}
There are 239 different campaignid's, which all should have a value of 1, but they all have 0.
Now i want to have per campaignid the total amount of numunits grouped, which i use the following statement:
db.orders.aggregate({$group: {_id: "$campaignid", Numunits: {$sum:" $numunits"}}})
It gives back the following result:
{ "_id" : 2146, "Numunits" : 0} , { "_id" : 2111, "Numunits" : 0} etc...
Now the expected result is:
{ "_id": 2146, "Numunits" : 93} , { "_id" : 2111, "Numunits" : 23} etc..
Mongo doesn't trim space for you if any. Try this:
db.orders.aggregate(
[
{$group: {
_id: "$campaignid",
Numunits: {$sum:"$numunits"}
}
}
])

Expressing this SQL as Mongo Query

I want to figure out the most active users on my site.
I have records of the form
{
"_id" : "db1855b0-f2f4-44eb-9dbb-81e27780c796",
"createdAt" : 1360497266621,
"profile" : { "name" : "test" },
"services" : { "resume":
{ "loginTokens" : [{
"token" : "82c01cb8-796a-4765-9366-d07c98c64f4d",
"when" : 1360497266624
},
{
"token" : "0e4bc0a4-e139-4804-8527-c416fb20f6b1",
"when" : 1360497474037
} ]
},
"twitter" : {
"accessToken" : "9314Sj9kKvSyosxTWPY5r57851C2ScZBCe",
"accessTokenSecret" : "UiDcJfOfjH7g9UiBEOBs",
"id" : 2933049,
"screenName" : "testname"
}
}
}
I want to be able to select users and order by the number of loginTokens.
In MySQL it would be something like:
SELECT id, COUNT(logins) AS logins
FROM users
GROUP BY id ORDER BY logins DESC
I've tried this on querymongo.com and i got an error (can't work with aliases/ cant order by non-column names)
What's the Mongo way to do this?
Thanks!
I just converted:
SELECT id, COUNT(logins)
FROM users
GROUP BY id
To:
db.users.group({
"key": {
"id": true
},
"initial": {
"countlogins": 0
},
"reduce": function(obj, prev) {
prev.countlogins++;
}
});
Hope this helps
Here is an example of what you said using the aggregation framework:
db.users.aggregate([
{$unwind: '$services.resume.loginTokens'},
{$group: {_id: '$_id', logins: {$sum: 1}}},
{$sort: {logins: -1}}
])
This should do the trick.