Finding an object in MongoDb that has a value within a range - mongodb

MongoDb 3.4.9
I have objects that look like this:
startIpNum:16779264
endIpNum:16781311
locId:47667
startIpNum:16781312
endIpNum:16785407
locId:879228
etc
How can I find just the object that has a range (between startIpNum and endIpNum) for 16779300?

db.collection.find({ startIpNum:{ $gte: 16779300 }, endIpNum:{$lte: 16779300} })
It includes both upper and lower limit

Related

MongoDB find document matching a coordinate comparison

I am currently working on a mongoDB database for a class project. However, I'm very new to it.
I must find all documents where the latitude is greater than a certain value: 39. Longitude value can be anything.
Please find below the example of one document, showing the global structure of the database.
Example
Looking at MongoDB's documentation, I have two hints:
Trying a nested document query ("end station location.coordinates.0:{$gt:39})
Yet, it is not working..
Trying some geometric intersection. As I'm very new to MongoDB, I don't know if it'd be the easiest way to find what's I'm looking for.
Could someone help me improving myself ?
Regards,
I think your problem is you are looking for values greater than 39 in the first position in the array. And these values in your example are negative numbers, so no one is grater than 39.
If you do the same query using $lt you will get results. Example here.
Also, to find values $gt: 39 you have to find the second position into the array:
db.collection.find({
"end station location.coordinates.1": {
"$gt": 39
}
})
Example here
Also, if you want to get the values if exists almost in one filed end station location or start station location you need $or operator like this:
db.collection.find({
"$or": [
{
"end station location.coordinates.1": {
"$gt": 39
}
},
{
"start station location.coordinates.1": {
"$gt": 39
}
}
]
})
Example here
And remember, you want to search by second position into the array, so you have to use coordinates.1.

MongoDB fast count of subdocuments - maybe trough index

I'm using MongoDB 4.0 on mongoDB Atlas cluster (3 replicas - 1 shard).
Assuming i have a collection that contains multiple documents.
Each of this documents holding an array out of subdocuments that represent cities in a certain year with additional information. An example document would look like that (i removed unessesary information to simplify example):
{_id:123,
cities:[
{name:"vienna",
year:1985
},
{name:"berlin",
year:2001
}
{name:"vienna",
year:1985
}
]}
I have a compound index on and year. What is the fastest way to count the occurrences of name and year combinations?
I already tried the following aggregation:
[{$unwind: {
path: '$cities'
}}, {$group: {
_id: {
name: 'cities.name',
year: '$cities.year'
},
count: {
$sum: 1
}
}}, {$project: {
count: 1,
name: '$_id.name',
year: '$_id.year',
_id: 0
}}]
Another approach i tried was a map-reduce in the following form - the map reduce performed a bit better ~30% less time needed.
map function:
function m() {
for (var i in this.cities) {
emit({
name: this.cities[i].name,
year: this.cities[i].year
},
1);
}
}
reduce function (also tried to replace sum with length, but surprisingly sum is faster):
function r(id, counts) {
return Array.sum(counts);
}
function call in mongoshell:
db.test.mapReduce(m,r,{out:"mr_test"})
Now i was asking myself - Is it possible to access the index? As far as i know it is a B+ tree that holds the pointers to the relevant documents on disk, therefore from a technical point of view I think is would be possible to iterate through all leaves of the index tree and just counting the pointers? Does anybody if this is possible?
Does anybody knows another way to solve this approach in a high performant way? (It is not possible to change the design, because of other dependencies of the software, we are running this on a very big dataset). Has anybody maybe experience in solve such task via shards?
The index will not be very helpful in this situation.
MongoDB indexes were designed for identifying documents that match a given critera.
If you create an index on {cities.name:1, cities.year:1}
This document:
{_id:123,
cities:[
{name:"vienna",
year:1985
},
{name:"berlin",
year:2001
}
{name:"vienna",
year:1985
}
]}
Will have 2 entries in the b-tree that refer to this document:
vienna|1985
berlin|2001
Even if it were possible to count the incidence of a specific key in the index, this does not necessarily correspond.
MongoDB does not provide a method to examine the raw entries in an index, and it explicitly refuses to use an index on a field containing an array for counting.
The MongoDB count command and helper functions all count documents, not elements inside of them. As you noticed, you can unwind the array and count the items in an aggregation pipeline, but at that point you've already loaded all of the documents into memory, so it's too late to make use of an index.

MongoDB: What is the fastest / is there a way to get the 200 documents with a closest timestamp to a specified list of 200 timestamps, say using a $in [duplicate]

Let's assume I have a collection with documents with a ratio attribute that is a floating point number.
{'ratio':1.437}
How do I write a query to find the single document with the closest value to a given integer without loading them all into memory using a driver and finding one with the smallest value of abs(x-ratio)?
Interesting problem. I don't know if you can do it in a single query, but you can do it in two:
var x = 1; // given integer
closestBelow = db.test.find({ratio: {$lte: x}}).sort({ratio: -1}).limit(1);
closestAbove = db.test.find({ratio: {$gt: x}}).sort({ratio: 1}).limit(1);
Then you just check which of the two docs has the ratio closest to the target integer.
MongoDB 3.2 Update
The 3.2 release adds support for the $abs absolute value aggregation operator which now allows this to be done in a single aggregate query:
var x = 1;
db.test.aggregate([
// Project a diff field that's the absolute difference along with the original doc.
{$project: {diff: {$abs: {$subtract: [x, '$ratio']}}, doc: '$$ROOT'}},
// Order the docs by diff
{$sort: {diff: 1}},
// Take the first one
{$limit: 1}
])
I have another idea, but very tricky and need to change your data structure.
You can use geolocation index which supported by mongodb
First, change your data to this structure and keep the second value with 0
{'ratio':[1.437, 0]}
Then you can use $near operator to find the the closest ratio value, and because the operator return a list sorted by distance with the integer you give, you have to use limit to get only the closest value.
db.places.find( { ratio : { $near : [50,0] } } ).limit(1)
If you don't want to do this, I think you can just use #JohnnyHK's answer :)

Meteor collection find sort after filtering

I've a collection of addresses, I would like to filter the collection to keep the 10 nearest address, then I would like to be able to sort them from the farther to the nearest.
Is that possible to achieve this within a single find request in meteor ?
The following gives me the 10 nearest addresses:
Addresses.find({}, {sort:{distance:1}, limit:10});
but they are ordered by increasing distance, obviously if I do set distance:-1 they will come by decreasing order but I will also get only the 10 farthest addresses…
You need the aggregation framework:
db.collection.aggregate(
{ $sort: { distance: 1 } },
{ $limit: 10 },
{ $sort: { distance: -1 } }
)
I hope the query is self-explanatory.
If you can't run an aggregation or native mongo query in MeteorJS, then you'll probably have to reverse the results you got from the DB query programatically.
If you fetch the result of your search and reverse it it should work.
Addresses.find({}, {sort:{distance:1}, limit:10}).fetch().reverse()
The only drawback is that now it's an array and not a cursor anymore

mongodb - Find document with closest integer value

Let's assume I have a collection with documents with a ratio attribute that is a floating point number.
{'ratio':1.437}
How do I write a query to find the single document with the closest value to a given integer without loading them all into memory using a driver and finding one with the smallest value of abs(x-ratio)?
Interesting problem. I don't know if you can do it in a single query, but you can do it in two:
var x = 1; // given integer
closestBelow = db.test.find({ratio: {$lte: x}}).sort({ratio: -1}).limit(1);
closestAbove = db.test.find({ratio: {$gt: x}}).sort({ratio: 1}).limit(1);
Then you just check which of the two docs has the ratio closest to the target integer.
MongoDB 3.2 Update
The 3.2 release adds support for the $abs absolute value aggregation operator which now allows this to be done in a single aggregate query:
var x = 1;
db.test.aggregate([
// Project a diff field that's the absolute difference along with the original doc.
{$project: {diff: {$abs: {$subtract: [x, '$ratio']}}, doc: '$$ROOT'}},
// Order the docs by diff
{$sort: {diff: 1}},
// Take the first one
{$limit: 1}
])
I have another idea, but very tricky and need to change your data structure.
You can use geolocation index which supported by mongodb
First, change your data to this structure and keep the second value with 0
{'ratio':[1.437, 0]}
Then you can use $near operator to find the the closest ratio value, and because the operator return a list sorted by distance with the integer you give, you have to use limit to get only the closest value.
db.places.find( { ratio : { $near : [50,0] } } ).limit(1)
If you don't want to do this, I think you can just use #JohnnyHK's answer :)