Error creating Geospatial index in MongoDB - mongodb

I have a collection ('stops') with 14000 records imported from a CSV. Included in each record is some geospatial data, which I've converted into an array, so each essentially looks like this:
{
_id: ...,
// other fields
"loc": [
153.019073,
-27.467834
]
}
When I run db.stops.ensureIndex({ loc: '2d' }) it gives the error:
location object expected, location array not in correct format
I guess that something's wrong in one of the fields, but I can't figure out which one. Any ideas?

The problem was that there was a single record which wasn't imported correctly (probably an empty line at the end of the file).
To find it (and later remove it), I used the $where operator:
db.stops.find({ $where: 'typeof this.loc[0] != "number"' })

Related

what is the proper way to use $nin operator with mongoDB

I want to find entries in my MongoDB collection that match some filters.
Each entry in my mongo collection looks like this data:
{
type: "admin"
senderId: "6131e7c597f50700160703fe"
read_by: [
{
Object_id: 614dbbf83ad51412f16c0757
readerId: "60b968dc5150a20015d6fcae"
}
]
},
{
type: "admin"
senderId: "6131e7c597f50700160703fe"
read_by: [
{}
]
}
What I want to achieve properly, is to filter on the collection and get only the entries that match 'admin' as type and that don't have the current user's ID in the read_by array (that is an array of objects)
I wrote this (and tried some other combinations with errors :) )
but it is not working, I get 0 entries on the end, but I expect to get one of the two as the second have it's read_by array empty.
Thank you very much!
I validated my solution using cloud.mongodb.com interface and the simplest following filter seems to do the job:
{ "read_by.readerId": {$ne:"60b968dc5150a20015d6fcae"}}
Only the record with empty array is being returned.
$nin operator works fine as well but if there is only single value for comparision then $ne should be enough.
{ "read_by.readerId": {$nin: ["60b968dc5150a20015d6fcae"]}}

updating Mongoose documents with nested arrays at multiple indexes

I'm having trouble updating a schema with a nested array to have one objectID in multiple rows of the array. Please help if you can!
My Schema looks like this:
var ProblemSchema = new Schema({
data : "etc..."
array1 : [{
_id : { type: 'String' },
array2: [{ type: Schema.Types.ObjectId}]
}]}
I can easily add an objectId to a SINGLE nested array using the $ operator in the update object like so:
var query = {array1._id : ID};
var update = {$push : {'array1.$.array2' : objectId}};
Problem.update(query, update)
I want to be able to, however, add the same objectId to MULTIPLE array2s (i.e. corresponding to different array1 ids) in one query, but the $ operator only matches to the first match to the query so I can't do it the way outlined above.
I'm also trying to avoid having a for loop on the server (I realize I could find() the correct document then use a for loop in which I manually push() the objectID to the correct array2s but the solution involves large overhead), can anyone think of a solution?
As of MongoDB 2.6, there's no way to do this with with a single update query. The $ positional operator is a placeholder for the first matching element in an array. There's a MongoDB feature request for updating all matching elements of an array, SERVER-1243, that you can track in the meantime.

Updating multiple MongoDB records in Sails.js

I need to update multiple records in mongodb.
From frontend logic , i got the array of id's as below.
ids: [ [ '530ac94c9ff87b5215a0d6e6', '530ac89a7345edc214618b25' ] ]
I have an array of ids as above , i need to update the folder field for all the records in that array.
I tried passing the id's to mongodb query as below , but still that doesn't work.
Post.native(function(err, collection) {
collection.update({
_id : {
"$in" : ids
}
}, { folder : 'X'}, {
multi : true
}, function(err, result) {
console.log(result);
});
});
Please help.
There seem to be two possible problems.
1) your ids array is not an array of ids, it's an array which has a single element which is itself an array, which has two elements. An array of ids would be `[ 'idvalue1', 'idvalue2']
2) your id values inside of arrays are strings - is that how you are storing your "_id" values? If they are ObjectId() type then they are not a string but a type ObjectId("stringhere") which is not the same type and won't be equal to "stringhere".
There is no reason to use the native method in this case. Just do:
Post.update({id : ids}, {folder : 'X'}).exec(console.log);
Waterline automatically does an "in" query when you set a criteria property to an array, and Sails-Mongo automatically translates "id" to "_id" and handles ObjectId translation for you.
Those strings look like the string representation of mongod ObjectIds, so probably what you want to do is turn them into ObjectIds before querying. Assuming you've corrected your problem with the extra level of nesting in the array, that is:
ids = ['530ac94c9ff87b5215a0d6e6', '530ac89a7345edc214618b25']
Then you want to do something like this:
oids = []
for (var i in ids)
oids.push(ObjectId(ids[i]))
db.c.find({_id: {$in: oids}})
Does that fix your problem?

MongoDB Find using Array

I have a mongoDB collection which contains a list of documents which contain (among other items) a time stamp and an address for each different type of device. The device address is in hexidecimal (eg. 0x1001, 0x2001, 0x3001, etc.).
On the server side, I'm trying to query the collection to see what documents exists within a certain date range, and for a list of device
Collection.find(
{"addr": data.devices.Controls, "time": {$gte:d0, $lte:d1}},{},
function (err, docs) {
if( err|| !docs) console.log("No data found");
else {
//I've simplified the code here...
}
}
);
d0 and d1 are my start and end dates... and the data.devices.Controls is a list of device addresses. If I add the line:
console.log("Controls: " + JSON.stringify(data.devices.Controls));
I can see on the server side that it prints out a list of addresses that I'm looking for (the actual print statement looks like: Controls: ["0x1001", "0x2001", "0x3001"].)
However, this find statement doesn't seem to return any data from the query. There's no error (as I don't see the "No Data Found" message)... It just doesn't seem to return any data. What's strange is that if I specify a specific element out of the Controls array (something like data.devices.Controls[0]...), then it works fine. I can specify any element in the array and it works... but by passing an entire array in the argument, it doesn't seem to work. Does anyone know why this happens (and how to fix it)?
You need to use the $in operator to match against an array of values; like this:
Collection.find(
{"addr": {$in: data.devices.Controls}, "time": {$gte:d0, $lte:d1}}, ...

Is it possible to query MongoDB by subfield object values?

I have documents like this:
db.planet.insert({
name: 'Earth',
stuff: {
'grass': 'green',
'sky': 'blue',
'sea': 'blue'
}
})
db.planet.insert({
name: 'Mars',
stuff: {
'dust': 'red',
'sky': 'yellow'
}
})
I want to find all planets that have at least some blue stuff (only earth in this case). How can I do that?
Catch: I tried solving this by using an array (instead of object) for stuff (stuff: [ { k: 'grass', v: 'green'},... ]) but I also need to be able to update (upsert to be exact) value of some stuff. For instance I must be able to do this:
db.planet.update({ name: 'Mars' }, {
'$set': {
'stuff.canals': 'brown',
'stuff.dust': 'reddish'
}
})
So, how can I find the planets with something blue on them? :)
Use the $or operator. The $or operator value should be an array, with the array containing conditions of which at least one must be true.
In your case, given the field names you have mentioned:
db.planet.find($or:[
{"stuff.sky":"blue"},
{"stuff.grass":"blue"},
{"stuff.sea":"blue"},
{"stuff.dust":"blue"},
{"stuff.canals":"blue")
])
See http://docs.mongodb.org/manual/reference/operator/or/
As there are a quite a number of different fields you want to query, you may want to keep an array of all these field names somewhere so you can generate the $or array programmatically.
I don't think there's a way to make the query without knowing the field names in advance. See mongodb query without field name .