Collection name error while importing Json to MongoDB - mongodb

As I was importing a new json file to my mongodb collection I've accidentally use just one '-' instead of 2. Eg.:
mongoimport --host=127.0.0.1 --db=dataBaseName -collection=people --file=importFile.json
I believe that due to the lack of the second '-', now I'm stuck with the following results when I type show collections:
people
ollection=people
I can't access, drop or interact with the second one. Apart from droping the database and starting over, is there a way around this issue?

You can rename the collection like:
> use YourDatabase
// Might wanna drop people collection first
> db.getCollection("ollection=people").renameCollection("people")
Hope This helps!

Related

How to prevent specific collection not to delete

I am on windows platform. I have a shell script which delete the whole database when cronjob cal this file.
File is
delete.sh
#!/usr/bin/env mongo
mongo 127.0.0.1:27021/test --eval "db.dropDatabase()"
Let's say I have a collection named as "Doctor" Now I don't want to delete that table.
Any idea how to acheive this.
can we use --excludeCollection here???
There is no such flag. Dropping database means dropping the whole database. If you need at least one collection to remain you need to keep the database. Collections don't exists without a database.
What you can do is to drop collections instead. Use db.getCollectionNames and drop them one by one excluding the ones you want to keep.
E.g. with filter:
mongo 127.0.0.1:27021/test --eval "db.getCollectionNames().filter(c=>!['Doctor'].includes(c)).forEach(c=>db.getCollection(c).drop())"
Or using getCollectionInfos with query filter:
mongo 127.0.0.1:27021/test --eval "db.getCollectionInfos({name:{$nin: ['Doctor']}}).forEach(({name})=>db.getCollection(name).drop())"
You may need to escape the dollar sign in $nin. I can't recall how shell scripts work on windows.

MongoDB Error Code 16755 - Can't extract geo keys & duplicate vertices

When I try to create an index on geometry db.polygons.createIndex({"geometry":"2dsphere"}), it stops at a certain polygon with the error code 16755. It says it Can't extract geo keys and Duplicate vertices: 18 and 20.
So upon further inspection, it seems like this happens when 2 nodes in a polygon are close together, or even duplicates.
I then go manually remove this node in QGIS and re-try the process, only to find there's another polygon with the same issue.
How can I fix this issue without having to repeat the entire process of fixing polygon > uploading to MongoDB > creating index? Is there a way I can find out how many polygons have this issue?
I hit a similar problem. I just needed to find the valid records in my dataset (I discarded the records with Duplicate Vertices).
I renamed the collection -
db.myCollection.renameCollection('myCollectionBk')
Then I added a single record from the original collection into a new collection and added a geospatial index to the collection
db.myCollection.insert(db.myCollectionBk.findOne()) // recreate the collection
db.myCollection.createIndex({geometry:"2dsphere"}) // create the index (assumes the geometry on the record is valid)
db.myCollection.remove({}) // remove the record
Then I added the valid records into the new collection.
db.myCollectionBk.find().forEach(function(x){
db.myCollection.insert(x);
})
Invalid records are simply ignored.
In your case you probably want to get the WriteResult from your insert, and look to see if it was successful. Something like
var errors = []
db.myCollectionBk.find().forEach(function(x){
var result = db.myCollection.insert(x);
if (result.writeError) {
errors.push({x._id:result.writeError.errmsg});
}
})
As another alternative, check out this question (I couldn't get this to work)
So what I did was, I first created the collection with the index and then tried inserting using mongoimport which gave me how many were inserted successfully.
> db.someNewCollection.createIndex({"geometry":"2dsphere"})
To insert GeoJSON into MongoDB I did the following:
$ jq --compact-output ".features" yourGeoJSON > output.geojson
$ mongoimport --db someDB -c someNewCollection --file "output.geojson" --jsonArray

How to remove an empty Mongo database with the same name as a populated database?

I accidentally created two databases with the same name. When I do show dbs in my Mongo shell, I get this:
> show dbs
admin (empty)
local 0.078GB
example_development (empty)
example_development 0.078GB
Is there a way to remove the empty db without tampering with the populated one?
The database names aren't the same, its just that one has a non-printable character in it which mongo shell's javascript interface is suppressing for you.
In mongo its up to the driver to make sure the user is not able to submit non-standard data to the server but it has been demonstrated that BSON is remarkably flexible in what it can store.
Since you're talking about an entire database the easiest way to fix this problem would be to shutdown mongo and remove the database files. You can find where those files are with the db.serverCmdLineOpts() command.
Wes Widner answer is correct in that you most likely have a non-printable character. However, rather than remove the files from the filesystem directly, I prefer a more programmatic approach. They key here is to never really call the database by its literal name, but instead keep a reference to the name in variable form:
List all databases
Filter those databases to match the criteria you're seeking
Transform the resulting list (array) into just the database names
Select the specific index of the db in question (I couldn't figure out a way to iterate through each resulting database and apply getSiblingDB to each of them).
Pass that into db.getSiblingDB and issue a db.dropDatabase
Working Example
use bogus;
db.createCollection('blah');
db.getCollectionNames(); // [ "blah", "system.indexes" ]
use admin;
db.adminCommand({listDatabases:1}).databases.filter(function(d){
return d.name === 'bogus';
}).map(function(d){
return d.name;
}); // [ "bogus" ]
// use [0] here since we now 'bogus' was at index 0 in previous
// getSiblingDB will allow us to issue dropDatabase on the string
// representation of the database
db.getSiblingDB(db.adminCommand({listDatabases:1}).databases.filter(function(d){
return d.name === 'bogus';
}).map(function(d){
return d.name;
})[0]).dropDatabase();
Tailoring It to Your Problem
Instead of specifically filtering by name, we want to filter by sizeOnDisk. Be sure not to select "admin" here, so run the adminCommand with the filter/map first to get the applicable index. Chances are "admin" will be at index 0, so your database in question will most likely be at index 1:
db.getSiblingDB(db.adminCommand({listDatabases:1}).databases.filter(function(d){
return !d.sizeOnDisk;
}).map(function(d){
return d.name;
})[1]).dropDatabase(); // note usage of [1] here

How can I rename a collection in MongoDB?

Is there a dead easy way to rename a collection in mongo? Something like:
db.originalCollectionName.rename('newCollectionName');
And if not, what is the best way to go about effectively renaming one?
Close. Use db.originalCollectionName.renameCollection('newCollectionName')
See http://www.mongodb.org/display/DOCS/renameCollection+Command
Assume that the database name is "mytestdb" and collection name is "orders". collection name change to orders2015 The simplest way is,
> use mytestdb
> db.orders.renameCollection( "orders2015" )
Note : db.collection.renameCollection() is not supported on sharded collections.
For those who cannot rename, because the name causes an issue like: SyntaxError: Unexpected token ILLEGAL, it is because the name is illegal.
You can work around this by calling with brackets notation: db["oldCollectionILLEGALName"].renameCollection("someBetterName")
In case you are using Node.js MongoDB driver:
mongoClient.db(dbName).collection('oldName').rename("newName");
https://mongodb.github.io/node-mongodb-native/3.5/api/Collection.html#rename
my case was using mongoose:
await mongoose.connection.collection("oldName").rename("newName");
Rename a collection in cmd:
cd C:\Program Files\MongoDB\Server\4.2\bin
mongo
use yourdb
db.yourcollection.renameCollection("someBetterName")
This example is made for MongoDB 4.2
You can use the following syntax to rename an existing collection in MongoDB.
db.originalCollectionName.renameCollection('newCollectionName')
For instance, if your existing collection name is 'demo' and want to rename to 'demo_updated' then, the query would be as follows:-
db.demo.renameCollection('demo_updated')
Thanks!

Is there a better way to export a mongodb query to a new collection?

What I want:
I have a master collection of products, I then want to filter them and put them in a separate collection.
db.masterproducts.find({category:"scuba gear"}).copyTo(db.newcollection)
Of course, I realise the 'copyTo' does not exist.
I thought I could do it with MapReduce as results are created in a new collection using the new 'out' parameter in v1.8; however this new collection is not a subset of my original collection. Or can it be if I use MapReduce correctly?
To get around it I am currently doing this:
Step 1:
/usr/local/mongodb/bin/mongodump --db database --collection masterproducts -q '{category:"scuba gear"}'
Step 2:
/usr/local/mongodb/bin/mongorestore -d database -c newcollection --drop packages.bson
My 2 step method just seems rather inefficient!
Any help greatly appreciated.
Thanks
Bob
You can iterate through your query result and save each item like this:
db.oldCollection.find(query).forEach(function(x){db.newCollection.save(x);})
You can create small server side javascript (like this one, just add filtering you want) and execute it using eval
You can use dump/restore in the way you described above
Copy collection command shoud be in mongodb soon (will be done in votes order)! See jira feature.
You should be able to create a subset with mapreduce (using 'out'). The problem is mapreduce has a special output format so your documents are going to be transformed (there is a JIRA ticket to add support for another format, but I can not find it at the moment). It is also going to be very inefficent :/
Copying a cursor to a collection makes a lot of sense, I suggest creating a ticket for this.
there is also toArray() method which can be used:
//create new collection
db.creatCollection("resultCollection")
// now query for type="foo" and insert the results into new collection
db.resultCollection.insert( (db.orginialCollection.find({type:'foo'}).toArray())