MongoDb "left join" with different column types - mongodb

I have two collections: User and UserProfile.
UserProfile references User by the property userId as UUID.
User collection have _id field but as string.
How can I "left join" these two collections to find out what documents don't have a match?
Here is what I got so far:
db.UserProfile.aggregate({
$lookup:
{
from: 'User',
localField: 'userId', // this is UUID
foreignField: '_id', // this is string
as: 'user'
}
})
Here are two sample entities:
User:
{
"_id" : "0c7e18b2-3682-444d-a62b-30e311e76891",
"userName" : "programad",
"normalizedUserName" : "PROGRAMAD",
"email" : "programad#gmail.com",
"normalizedEmail" : "PROGRAMAD#GMAIL.COM",
"emailConfirmed" : true,
"concurrencyStamp" : "56d3d071-0e30-458a-880a-ed75e20863a9",
"lockoutEnabled" : true,
"roles" : [ ],
"claims" : [ ],
"logins" : [ ],
"tokens" : [ ],
"recoveryCodes" : [ ]
}
UserProfile:
{
"_id" : UUID("a4d5b6d5-f181-4267-5b81-08d64d02d681"),
"userId" : UUID("0c7e18b2-3682-444d-a62b-30e311e76891"),
"createDate" : ISODate("2018-08-01T00:00:00.000-03:00"),
"type" : "Personal",
"name" : "Daniel Gomes",
"motto" : "Code Lover",
"bio" : "bio yadda yadda",
"studioName" : "My studio name",
"location" : "Santos/Brazil",
"externalLinks" : [ ]
}

Ok, a gentleman called Vignan Yarlagadda helped me on this.
I needed to find wich profiles lack users or vice-versa.
He came around with this:
db.UserMissing.drop();
var cur = db.UserProfile.find({"_id":{"$exists":1}}).addOption(16);
cur.forEach(function(x){
db.UserMissing.insert({"_id":x.userId,"userId":x.userId})
});
var cur = db.User.find({"_id":{"$exists":1}}).addOption(16);
cur.forEach(function(x){
var string=x._id;
var y=UUID(string);
db.UserProfile.find({"userId":y}).forEach(function(doc){
db.UserMissing.update({"userId":doc.userId},{"$set":{"Matching":true}},{"multi":true});
});
});
db.UserMissing.find({"Matching":{"$exists":0}});
It creates **a temporary collection** called UserMissing and I can see witch ones to focus my attention.

Related

how to update one table with the _id from another table in Mongodb

I exported data from a MySQL database into JSON and imported it into MongoDB. The problem:
When I imported clients, MongoDB created its own _id field (I know this is built in functionality, but MySQL used a clientID, autoincrementing integer).
SO, when I imported my appointments collection, the clientID was renamed oldClientID. I'd like the clientID field to be the ObjectID of the corresponding client.
My schemas:
const apptSchema = new mongoose.Schema({
ID: Number,
clientID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Client'
},
oldClientID: Number,
...other field data
});
const clientSchema = new mongoose.Schema({
ID: Number,
familyID: Number,
first: String,
last: String,
});
Sample Patient Data:
{
"_id" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"ID" : 18,
"familyID" : 6,
"first" : "Jane",
"last" : "Doe"
}
Sample Appointment Data
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
What appointments should look like:
{
"_id" : ObjectId("5d82c8b95627367d122087f9"),
"ID" : 1885,
"clientID": ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-08-05T11:20:00Z"),
"note" : ""
},
{
"_id" : ObjectId("5d82c8b95627367d122088a8"),
"ID" : 2066,
"clientID" : ObjectId("5d82240f7c8ddd03b62aee6a"),
"oldPatientID" : 18,
"scheduled" : ISODate("2015-09-17T16:00:00Z"),
"note" : ""
}
I am open to learning how to achieve this in the mongo shell or using mongoose in express (or if there is another cool way, like in Robo3T).
MongoDB will always use _id as the primary key, this behavior cannot be overwritten, though you can use the _id with values from your custom id. Though this might be confusing, it is better to use indexing on your custom id, and you don't need to use ObjectId for the custom index field, but can use your own custom id schema, like UUID or an incrementing integer value etc. though it has to be generated/incremented by you or some framework, like JPA
Check Indexes
For Mongoose, you can do;
new mongoose.Schema({
customId: { type: Number, index: true }
...other field data
});
with index: true
Ok, this worked out for me, although I'm sure there has to be an easier way:
db.getCollection("appts").aggregate(
[
{
"$lookup" : {
"from" : "clients",
"localField" : "clientID",
"foreignField" : "ID",
"as" : "CLIENT"
}
},
{
"$lookup" : {
"from" : "appttypes",
"localField" : "type",
"foreignField" : "ID",
"as" : "TYPE"
}
},
{
"$lookup" : {
"from" : "apptstatuses",
"localField" : "status",
"foreignField" : "ID",
"as" : "STATUS"
}
},
{
"$project" : {
"_id" : "$_id",
"clientID" : "$CLIENT._id",
"scheduled" : "$scheduled",
"note" : "$note",
}
},
{
"$out" : "apptslinked"
}
]
);
Then I exported that as JSON, dropped the appts table, and did a mongoimport using that file.

Mongodb update and delete operations in a single query

I have documents in which I would like to update the hostUser with one of the members of the document,also have to delete the record from the member document and add the chips of the deleted member in the club chips.
Here is the sample document.
{
"_id" : "1002",
"hostUser" : "1111111111",
"clubChips" : 10000,
"requests" : {},
"profile" : {
"clubname" : "AAAAA",
"image" : "0"
},
"tables" : [
"SJCA3S0Wm"
],
"isDeleted" : false,
"members" : {
"1111111111" : {
"chips" : 0,
"id" : "1111111111"
},
"2222222222" : {
"chips" : 0,
"id" : "2222222222"
}
}
}
This is what I have tried.
db.getCollection('test').updateMany({"hostUser":"1111111111"},
{"$set":{"hostUser":"2222222222"},"$unset":{"members.1111111111":""}})
This is how you would handle unset and set in a single call to updateMany. Can you please clarify what you meant by "check if the values exist in the member field"?
db.getCollection('test').updateMany(
{"hostUser":"1111111111"},
{
'$set': {"hostUser":"2222222222"} ,
'$unset': {"members.1111111111":""}
}
)

How to delete depricated string fields in options document?

Lets say I have a collections 'testCol' with document validation options in its options document.
{
"name" : "testCol",
"type" : "collection",
"options" : {
"validator" : {
"$or" : [
{
"phone" : {
"$type" : "string"
}
},
]
},
"validationLevel" : "moderate",
"validationAction" : "error"
},
...
}
Lets also say I want to delete these options (I am aware that I can set 'validationLevel' to 'off').
I can run db.runCommand('colMod'': testCol', validator: {}) and mongoDB will delete the field 'validator' from the options document. But I can't do the same for 'validationLevel' and 'validationAction'. db.runCommand('colMod'': testCol', validationLevel: ''), does not change anything which leaves me with something like this:
{
"name" : "testCol",
"type" : "collection",
"options" : {
"validationLevel" : "moderate",
"validationAction" : "error"
},
...
}
This is just unclean! Is there a way to get rid of that deprecated string-field options or a way to manipulate/access the options document of a collection directly?

Query given list of values equivalent to sql IN

I am stuck trying to figure out how to use the equivalent of "IN" in sql with MongoDB as I am not getting any results.
Here is sample output of the record/document:
[
{
"_id" : ObjectId("12348749e4b04b2d017ff78e"),
"account" : "foo",
"archivedFilteredEvents" : [
{
"id" : "all_events",
"name" : "All Events",
"enabled" : false
},
{
"id" : "f123dsad2",
"name" : "test1",
"enabled" : true
}
]
Here is the query I need help with:
printjson(db.mytestdb_profiles.find({
"account" : "foo",
"archivedFilteredEvents.id" : [ "all_events","f123dsad2"]}
));
I am basically looking for the equivalent of:
select id, name, enabled
from mytestdb_profiles
where account = 'foo'
and id.archivedFilteredDEvents IN ('all_events', 'f123dsad2');
You're just missing the $in operator in your query:
db.mytestdb_profiles.find({
"account" : "foo",
"archivedFilteredEvents.id" : { $in: [ "all_events","f123dsad2"] } }
)

meteor client find is not working due to $eq

I subscribed to my servers's publication as follows:
Template.observedQuestions.onCreated(function(){
var self = this;
self.autorun(function(){
self.subscribe('observedQuestionsFeed');
});
});
Now I need to fetch my data using helper function:
Template.observedQuestions.helpers({
observedQuestionsList : function(){
questions = Questions.find({
observedByUsers : {$exists: true,$elemMatch:{$eq:Meteor.userId()}}});
return questions;
}
});
but it does not work due to $eq being not recognised in minimongo.
How to solve it?
doc sample:
{
"_id" : "rP4JP8jkprwwi3ZCp",
"qUserId" : "NLLW3RBXqnbSGuZ3n",
"type" : "question",
"date" : ISODate("2016-02-13T11:23:10.845Z"),
"subject" : "test",
"question" : "test",
"replies" : [
{
"rID" : "LphcqKnkTHf25SCwq",
"rUserID" : "NLLW3RBXqnbSGuZ3n",
"date" : ISODate("2016-02-13T11:23:10.847Z"),
"answer" : "reply1."
},
{
"rID" : "HxaohnEgxwNJLtf2z",
"rUserID" : "NLLW3RBXqnbSGuZ22",
"date" : ISODate("2016-02-13T11:23:10.848Z"),
"answer" : "reply2"
}
],
"observedByUsers" : [ "Bi24LGozvtihxFrNe" ]
}
Judging from your sample Questions document, the field observedByUsers is a simple array which contains user IDs.
As a result, you could simply use the following query:
Questions.find({observedByUsers: Meteor.userId()});