Get the latest year in MongoDB - json

While working on a project, I came across a problem that I can't seem to find the solution for anywhere.
I'm working with NoSQLBooster for MongoDB and I need to fetch the most recent year present in my data.
I don't want to sort it in a descending way (doing so shows me all the values, and I can see that the year 2018 is the latest), but I want it to just present the number 2018.
Does anyone know how I can do this?
Thank you in advance!

This is pretty fast:
var x= db.find({},{_id:1}).sort(_id:-1).limit(1)
x._id.getTimestamp()

You can use $group (aggregation)
db.aggregate(
[
{
$group :
{
_id : null,
maxYear: { $max: "$yearField" }
}
}
]
)

Related

Compare hour of dates in mongo find method

I have mongo documents containing a field createAt date. I would like to search for all documents where
the hour of createAt at 8 o'clock in the morning of everyday (between 8:00am and 8:00am)
, but I have no clue how to write the query.
In MySQL I can write it like this:
select * from table where hour(createAt)= 8
You can use $hour with $expr.
db.collection.find({
$expr: {
$eq: [
{
$hour: "$createdAt"
},
8
]
}
})
Sample Mongo Playground
Your question has already been resolved.
I wrote you an example on the playground.

REST POST json body to support complex query advice

I'm fairly new to REST. All of our legacy webservices were SOAP based with enterprise (ORACLE or DB2) databases. We are now moving to REST/couchbase.
Our team is looking into implementing a complex query method. We already have implemented simple query methods using GET, for example GET returns all entries and a GET/067e6162-3b6f-4ae2-a171-2470b63dff00 would return the entry for 067e6162-3b6f-4ae2-a171-2470b63dff00.
We want to support a query method that would support receiving several query parameters such a list of Ids and date ranges. The number of Ids can number into a few thousand and because of this, we realize we cannot pass these query parameters in a GET HTTP header since there is a limit on header size.
We are starting to look into passing our query parameters into the JSON body of a POST request. For example, we could have client pass in a few thousand Ids as an array and also pass in a date range, so we'd have each query param/filter be an object. The JSON body would then be an array of objects. For example:
{
"action" : "search",
"queryParameters" : {
[
{
“operation”: “in”,
"key" : "name.of.attribute.Id",
"value" : "[{ "id: "067e6162-3b6f-4ae2-a171-2470b63dff00"}, {"id": "next id"....}],
},
{
“operation”: “greater”,
"key" : "name.of.attribute “,
"value" : "8/20/2016"
},
{
“operation”: “less”,
"key" : "name.of.attribute “,
"value" : "8/31/2016"
}
]
}
The back end code would then receive POST and read the body. It would see action is a search and then look for any entries in the list that are in the list of Ids that are in the date range of > 8/20/2016 and < 8/31/2016.
I've been trying to look online for tips/best practices on how best to structure the JSON body for complex queries but have not found much. So any tips, guidance or advice would be greatly appreciated.
thanks.

How sort json array multiple times in swift

I am trying to sort an array by a few values, not just one but three I can sort it like this
mysocialArray.sort({$0["date"] > $1["date"]})
This works fine, but i can find any where how to then sort it again so i get them sorted on time and another sort. SO should sort three times. When i just add another sort it is not taking the date into account.
The sorted json output will then be loaded in arrays as strings to display on the viewcontroller
How should I solve this?
thanks
Given your requirements of "This way the latest post that not yet have been read are at the top", looks like you are looking to sort by multiple criteria. I typed this in the dark so you may have to adjust it to fit your case:
mySocialArray.sort {
// First sort by read status. Assuming read is of type Bool
let (read1, read2) = ($0["read"] ? 1 : 0, $1["read"] ? 1 : 0)
if read1 != read2 {
return read1 > read2
}
// Then short by date. I assume date is of type NSDate
let (date1, date2) = ($0["date"], $1["date"])
if date1.timeIntervalSince1970 != date2.timeIntervalSince1970 {
return date1 > date2
}
// And lastly sort by time
return $0["time"] > $1["time"]
}

Limiting and sorting by different properties on couchbase

Given a JSON document on couchbase, for example, a milestone collections, which is similar to this:
{
"milestoneDate" : /Date(1335191824495+0100)/,
"companyId" : 43,
"ownerUserId": 475,
"participants" : [
{
"userId": 2,
"docId" : "132546"
},
{
"userId": 67,
"docId" : "153"
}
]
}
If I were to select all the milestones of the company 43 and want to order them by latest first.. my view on couchbase would be something similar to this:
function (doc, meta) {
if(doc.companyId && doc.milestoneDate)
{
//key made up of date particles + company id
var eventKey = dateToArray(new Date(parseInt(doc.milestoneDate.substr(6))));
eventKey.push(doc.companyId);
emit(eventKey, null);
}
}
I do get both dates and the company Id on rest urls.. however, being quite new to couchbase, I am unable to work out how to restrict the view to return only milestones of company 43
The return key is similar to this:
"key":[2013,6,19,16,11,25,14]
where the last element (14) is the company id.. which is quite obviously wrong.
The query parameters that I have tried are:
&descending=true&startkey=[{},43]
&descending=true&startkey=[{},43]&endKey=[{},43]
tried adding companyId to value but couldn't restrict return results by value.
And according to couchbase documentation I need the date parts in the beginning to sort them. How do I restrict them by company id now, please?
thanks.
Put the company id at the start of the array, and because you'll be limiting by company id, couchbase sorts by company id and then by date array so you will be only ever getting the one company's milestone documents
I'd modify the view to emit
emit([doc.copmanyId, eventKey], null);
and then you can query the view with
&descending=true&startkey=[43,{}]
This was what worked for me previously..
I went back and tried it with end key and this seems to work - restricts and orders as required:
&descending=true&startkey=[43,{}]&endkey=[42,{}]
or
&descending=true&startkey=[43,{}]&endkey=[43,{}]&inclusive_end=true
either specify the next incremented/decremented value (based on descending flag) with end key, or use the same endkey as startkey and set inclusiveEnd to true
Both of these options should work fine. (I only tested the one with endkey=42 but they should both work)

Couchbase Multiple Keys

I presume a simple question. I have the following data.
I want to search for all rows where the ID is > 2 but < 8 and the Price is > 30
I have used various versions of: startkey=["2", null] or even something like startkey=["2", "30"] just for testing.
It only ever seems to run both conditions on the first row. So if I do: startkey=["2", "30"] then I get back:
{"id":"3","key":["3","30"],"value":null},
{"id":"4","key":["4","30"],"value":null},
{"id":"5","key":["5","20"],"value":null},
{"id":"6","key":["6","60"],"value":null},
{"id":"8","key":["8","60"],"value":null}
Why is row 5 there?
I am starting to get the view that I need to handle this in the code (.net) and make multiple calls somehow... I can't seem to find anything on this that works....
Note: I have tried doing say a loop with for (i = 0; i < doc.ID.length; i++) and then using doc.ID[i] but it never returns anything....
Currently I just have
function (doc, meta) {
emit([doc.ID, doc.Price ],null);
}
Essentially I want to have a search where there are 5 input keys that a user has. So do I need to make 5 calls and then keep taking data from the previous output as the source for the next???
Other references I have looked at include: the manual
Thanks in advance,
Kindest Regards
Robin
This is a common misconception, with a compound array index key, it's still treated as a string, therefore the index key [2,10] is actually "[2,10]", and the index key [5,20], is actually "[5,20]".
So the reason that startkey=["2", "30"]shows the {"id":"5","key":["5","20"],"value":null}, row is because as a string it is > startkey.
Likewise, the Query startkey=[2,10]&endkey=[5,10] returns
{"total_rows":7,"rows":[
{"id":"2","key":[2,20],"value":null},
{"id":"3","key":[3,30],"value":null},
{"id":"4","key":[4,30],"value":null}
]
}
because startkey="[2,10]" < "[2,20]" && "[4,30]" < "[5,10]"=endkey, but "[5,20]" is not within that string Range.
Range Queries with startkey and endkey
startkey => endkey is a Range query using strcmp(), the group and group level is based on the string, where the comma is separating string tokens.
A Good Reference Link (since Couchbase Views work much like Apache CouchDB Views (inspired by them))
http://wiki.apache.org/couchdb/View_collation#Collation_Specification
Spatial View/Query
To achieve the result you are trying for, you could also write a Spatial View to have multi-dimensional Queries, numeric only. While you might not initially think of it
function (doc, meta) {
emit({
type: "Point",
coordinates: [doc.ID, doc.Price]
}, meta.id);
}
The Query would be a Bounding Box Query:
&bbox=2,0,8,30
{"total_rows":0,"rows":[
{"id":"2","bbox":[2,20,2,20],"geometry":{"type":"Point","coordinates":[2,20]},"value":"2"},
{"id":"3","bbox":[3,30,3,30],"geometry":{"type":"Point","coordinates":[3,30]},"value":"3"},
{"id":"4","bbox":[4,30,4,30],"geometry":{"type":"Point","coordinates":[4,30]},"value":"4"},
{"id":"5","bbox":[5,20,5,20],"geometry":{"type":"Point","coordinates":[5,20]},"value":"5"}
]
}
Another Query:
&bbox=2,30,8,30
{"total_rows":0,"rows":[
{"id":"3","bbox":[3,30,3,30],"geometry":{"type":"Point","coordinates":[3,30]},"value":"3"},
{"id":"4","bbox":[4,30,4,30],"geometry":{"type":"Point","coordinates":[4,30]},"value":"4"}
]
}