E11000 duplicate key error collection {info.subs: null} - mongodb

My app isn't letting me create more than one profile for some reason. Here's the setup in the service file:
//This finds the profile if it exists
async getProfile(user) {
let profile = await dbContext.Profile.findOne({
email: user.email
});
profile = await createProfileIfNeeded(profile, user);
await mergeSubsIfNeeded(profile, user);
return profile;
}
//This is supposed to create one if one doesn't exist
async function createProfileIfNeeded(profile, user) {
if (!profile) {
profile = await dbContext.Profile.create({
...user,
subs: [user.sub]
});
}
return profile;
}
It works for the first user, but when I make another, I get the error:
{"error":{"message":"MongoError: E11000 duplicate key error collection: TownMiner.profiles index: info.subs_1 dup key: { info.subs: null }","status":400},"url":"/api/profile"}
What's confusing is that subs are set via Auth0. When I look at it with a break-point in the server, it shows all the info there. Also, when I look in my MongoDB collections, nowhere does it say that any of the values are "null". I've used this same setup for a few projects now and they've all worked perfectly (and this new project is cloned from the same template). Also noted to make sure that the sub info is all different and it is.
This is the MongoDB collection:
_id: ObjectId("***")
subs:Array
0:"auth0|***dda6a"
1:"auth0|***aa288
name:"kevin#test.com"
picture:"https://s.gravatar.com/avatar/c6788456e2639d2d10823298cc219aaf?s=480&r..."
email:"kevin#test.com"
createdAt:2020-08-07T21:23:05.867+00:00
updatedAt:2020-08-17T17:24:05.583+00:00
__v:1
I've looked at the other answers for similar questions on here but couldn't quite find where it fit into this project. Any help would be great. Thanks!

There is a unique index in the TownMiner.profiles collection on {info.subs:1}.
That sample document doesn't include an info field, so the value entered in the index for that document would be null.
Since the index is tagged unique, the mongod will not permit you to insert any other document that would also be entered into the info.subs index using null.

Turns out the error was because I went on the mongoDB site and manually added a collection and probably set it up wrong. I deleted it and let my app build the collection itself and it seems to be working fine. Thank you for taking time to help! Always appreciated!

Related

How to determine newly inserted data upon using upsert? prisma

I have a working code below that inserts a data if it does not exist (but not updates if it exist). In below implementation I am looping upsert, and it just works fine.
My question is, how to get those newly inserted data? (exclude data that is already existing). Do have idea how to achieve this, in a shortest way as possible?
I did some research about it and found this possible github solution, but I don't get the point. Because it also returning data even its already existing.
this.data = await prisma.$transaction(
temp.map((provider) =>
prisma.provider.upsert({
where: {
user_id_api_key: {
user_id: provider.user_id,
api_key: provider.api_key
}
},
create: provider,
update: {}
})
)
)
console.log(this.data) // it still return data even if its already existing

Can I use flutter to create an index on firestore?

I'm using the following flutter code to query firestore which orders the data using the field timestamp.
var results = Firestore.instance.collection('post').orderBy('timestamp').getDocuments().then((value) {
var list = value.documents;
return list.map((doc) {
return doc.documentID;
}).toList();
});
When I run this code, it throws the below exception saying an index is required:
W/Firestore(31110): (21.3.0) [Firestore]: Listen for Query(app/jQH7Fp9xCZWYiqZRe7lE/post where readAccess array_contains_any [WzKImODx6WYVqdSW3D9Az3xrUnM2, PUBLIC] order by -timestamp, -name) failed: Status{code=FAILED_PRECONDITION, description=The query requires an index. You can create it here: https://console.firebase.google.com/v1/r/project/....
The exception even comes with a nice link. When opening that link, a nice UI pops up giving me the ability to create the index, with just a simple click:
Question: simple as the above may seem, I'm not very happy with this. I prefer to be able to create the index from fluttercode. In code I'm looking for something like the below:
Firestore.instance.collection('post').API-TO-CREATE-INDEX('timestamp');
Does it exist? Please advise. Many thanks.
It's not possible to create an index from client apps. You have three main choices:
Clicking the link you already saw.
Using the Firebase CLI to deploy the index from the command line.
Using the gcloud CLI to also deploy from the command line
See also the documentation on managing indexes.

Meteor.subscribe on server side

I want to create a backend service which monitors a mongodb collection for new entries. As those are being created, I wish to run processing and update them.
I thought doing so with a Meteor service/app would be a wise idea because Meteor uses 'oplog tailing' which seems ideal for this purpose (I'd rather avoid polling if possible).
As such, I figured creating a minimal server-side-only app should solve it.
So basically, I need something along these lines:
if (Meteor.isServer) {
MyCollection = new Mongo.Collection('myCollection');
Meteor.publish('myCollectionPub', function () {
return MyCollection.find({ some: criteria... });
}
// is there such a thing?
Meteor.serverSideSubscribe('MyCollectionPub',
function (newDocs) {
// process/update newDocs
});
}
According to the Meteor docs, I cannot use Meteor.subscribe() on the server (and indeed it crashes if I try).
Question is:
Are there ways of 'subscribing' to collection updates on the server?
The PeerLibrary server-autorun package (along with it's dependant, reactive-mongo) will provide you with easy server-side observation of collections.
An alternative to #tarmes suggestion is the collection-hooks package, however as pointed out by David Weldon, it will only trigger in instance it is run in:
https://github.com/matb33/meteor-collection-hooks
MyCollection.after.insert(function (userId, doc) {
// ...
});
If you need it to run even when another instance makes a change in the mongo database, you can observe a cursor that is returned from your collection:
MyCollection.find({created_at : {$gt: some_current_time}}).observe({
added: function(item) {
// Alert code
}
});

How to handle changes to db in meteor/mongo?

I'm a couple hours new to Meteor and Mongo, coming from a Rails background and trying to understand how migrations work - or don't maybe?
I have a server/bootstrap.js file that I use to seed some data:
// if the database is empty on server start, create some sample data.
Meteor.startup(function () {
if (Users.find().count() === 0) {
var userData = [
{ name: 'Cool guy' },
{ name: 'Other dude' }
];
for (var i = 0; userData.length; i++) {
var userId = Users.insert({
name: userData[i].name
});
}
}
});
It seems like every time I want to change the database, say to add a new field, I have to run meteor reset to get it to pick up the changes.
But what happens if I create records or other data through the UI that I want to keep? In Rails, working with MySQL or PostgreSQL, I'd create a migration to create new fields without blowing away the entire database.
How does this work with Meteor and Mongo? Also thinking of the case of rolling out new changes from development to production. Thanks!
-- Update: 2013/09/24 --
Apparently, the schema-less nature of Mongo reduces or eliminates the need for migrations. In my case, modifying userData to add new fields won't work after it runs initially because of the Users count check - which is why I kept running meteor reset. I'll need to rethink my approach here and study up.
That said, there are projects out there that use migrations, like Telescope: https://github.com/SachaG/Telescope/blob/master/server/migrations.js
I also found the tutorial at http://try.mongodb.org/ useful.
First of all, your code is perfectly valid. And you know that.
mrt reset gives you a 'fresh' - empty database (as mentionned already).
If you want to reset a particular collection, you can do it so :
MyCollection.remove({});
But you have to understand the nature of NoSQL : there are no constraints on the data. It could be called NoREL (as in not a relational database, source : Wikipedia ).
MongoDB is also schema-less.
This means that you can use any field you want in your data. This is up to you (the programmer) to enforce specific constraints if you want some. In other words, there is no logic on the mongo side. It should accept any data you throw at it, just like Hubert OG demonstrated. Your code snippet could be :
// if the database is empty on server start, create some sample data.
Meteor.startup(function () {
if (Users.find().count() === 0) {
var userData = [
{ name: 'Cool guy' },
{ name: 'Other dude' },
{ nickname: 'Yet another dude' } // this line shows that mongo takes what you throw him
];
for (var i = 0; userData.length; i++) {
var userId = Users.insert({
name: userData[i].name
});
}
}
});
Source : http://www.mongodb.com/nosql
There is no need for migration there. You only have to add the logic in your application code.
Note : To import/export a database, you can have a look there : mongo import/export doc, and maybe at the db.copyDatabase(origin, destination, hostname) function.
There are no migrations in Mongo — there is no scheme! If you want to add a new field that was not there before, just do it and it will work. You can even have completely different documents in the same collection!
Items.insert({name: "keyboard", type: "input", interface: "usb"});
Items.insert({cherries: true, count: 5, unit: "buckets", taste: "awesome"});
This will just work. One of main reasons to use NoSQL (and advantages of Meteor over Rails) is that you don't have migrations to worry about.
Using mrt reset to change db model is a terrible idea. What it actually does is complete reset of db — it removes all of your data! While it's sometimes usefull in development, I bet it's not what you want in this case.

Meteor.js - Publish function not working: Coffeescript

I am having some trouble making the publish function work with Meteor. The code I am using is as follows:
Meteor.publish "adminArea", () ->
Meteor.users.find({
admin: true
}, {
fields: {
permissions: 1
}
})
and I am subscribing with:
Meteor.subscribe "adminArea"
This doesn't work though, when I run Meteor.user() in the console it just returns the default options.
If I run db.users.find({"admin": "true"}) in Mongo the correct information is returned.
The annoying thing is, this used to work perfectly until I reset my database with Meteor reset. Would this be messing it up or does anyone know what I am doing wrong now?
Thanks for any help.
I have now fixed this issue and it was complete error on my part. I had forgot to add the permissions field to the user in the database so when it ran the query, it would find admin: true but then be unable to return the permissions field because it didn't exist.
So note to self: Always add the necessary fields to the user.
Oops!
Thanks