Mongo Conditional Condition in Node - node.js

I want to be able to have an API that can filter based on a date. So you pass in something like the following:
dob: {
date: new Date("5/22/1955"),
filter: 'lt'
}
This should return all records with DOB less than the date, but if "gte" was passed in the filter, than it should return all records with DOB greater than or equal to the date.
Obviously, the Mongo queries would be
dobQuery = {dob: {gte: data.dob.date}};
dobQuery = {dob: {lt: data.dob.date}};
But how could I make this conditional? I want to write something like this, but of course this doesn't work:
dobQuery = {dob : {"$" + data.dob.filter: data.dob.date}};
How can I write that out?

Build dobQuery up programmatically using bracket notation:
dobQuery = {dob: {}};
dobQuery.dob['$' + data.dob.filter] = data.dob.date;

Related

Why am I unable to change values of a Mongoose object to a different type ‘directly’?

I've just spent a good hour figuring out something mind-boggling (at least to me, as a JS noob) and I'd like to understand the underlying logic (or just why it works this way, because I think it's illogical and quite unexpected).
Suppose I'm using Mongoose to retrieve documents from a database, some or all of which include a date property (created with new Date()), a numeric property, and a string property.
[{
string: 'foo',
date: '2018-10-13T21:11:39.244Z',
number: 10
},
...
{
string: 'bar',
date: '2018-10-13T21:12:39.244Z',
number: 20
}]
I thus obtain an array of objects and now want to take the date property for each object and change the value to a string, so I do something like:
doc.find({}, (err, list) => {
list.forEach((item, index) => {
list[index].date = 'new value'
})
})
But I can't do that!
I can do list[index].string = 'new value' as well as list[index].date = new Date() but I can't change values that are of a different type, in this example date and number.
However, when I do list[index]._doc.date = 'new value', which took so long to figure out because I didn't know Mongoose objects weren't just plain old objects and focused on solving problems I didn't have instead, I can modify the value just fine.
It appears that the mongoose object somehow translates obj.key to obj._doc.key only if the type of the value matches but I'd appreciate a more detailed explanation than my uneducated guesses.
I suppose you want to use multi type on a document field, Mongoose support this by "Mixed" type when you define the Schema.
You can get more detail from https://mongoosejs.com/docs/schematypes.html#mixed.

How truncate time while querying documents for date comparison in Cosmos Db

I have document contains properties like this
{
"id":"1bd13f8f-b56a-48cb-9b49-7fc4d88beeac",
"name":"Sam",
"createdOnDateTime": "2018-07-23T12:47:42.6407069Z"
}
I want to query a document on basis of createdOnDateTime which is stored as string.
query e.g. -
SELECT * FROM c where c.createdOnDateTime>='2018-07-23' AND c.createdOnDateTime<='2018-07-23'
This will return all documents which are created on that day.
I am providing date value from date selector which gives only date without time so, it gives me problem while comparing date.
Is there any way to remove time from createdOnDateTime property or is there any other way to achieve this?
CosmosDB clients are storing timestamps in ISO8601 format and one of the good reasons to do so is that its lexicographical order matches the flow of time. Meaning - you can sort and compare those strings and get them ordered by time they represent.
So in this case you don't need to remove time components just modify the passed in parameters to get the result you need. If you want all entries from entire date of 2018-07-23 then you can use query:
SELECT * FROM c
WHERE c.createdOnDateTime >= '2018-07-23'
AND c.createdOnDateTime < '2018-07-24'
Please note that this query can use a RANGE index on createdOnDateTime.
Please use User Defined Function to implement your requirement, no need to update createdOnDateTime property.
UDF:
function con(date){
var myDate = new Date(date);
var month = myDate.getMonth()+1;
if(month<10){
month = "0"+month;
}
return myDate.getFullYear()+"-"+month+"-"+myDate.getDate();
}
SQL:
SELECT c.id,c.createdOnDateTime FROM c where udf.con(c.createdOnDateTime)>='2018-07-23' AND udf.con(c.createdOnDateTime)<='2018-07-23'
Output :
Hope it helps you.

TimeZone proplem in sequelize

Table name like users following columns are there
*Id -------------- (int type)
*DateandTime --------(Date type)
*Name -------------(varchar type)
I already insert one row like
Id = 123
Name = MR.X
DateandTime = 2018-01-12 06:22:06
Now select query in sequelize
model.user.findAll({
attributes: ['ID','DateandTime','NAME'],
where: {ID: useId} })
.then((userResult) => {
....... })
but getting DateandTime "2018-01-12T06:22:06.000Z"
You are getting out exactly what you put in. You have inserted a row as a string and it has been converted to a UTC date, it has not been stored the same as the string you put in.
When requesting it back out again, it is returning the date you put in, but from its database date form, not the original string.
You need to either store the date string as a string (varchar) if you just want the value as-is. Or, if you need to use the date for any date related functions, when you retrieve it back to display, you need to convert it to the string value you want.
I suggest using moment.js
const stringDate = moment(date).format('YYYY-MM-DD HH:mm');

mutivalue date field search not working

I have a multivalue field called freeDaysPool which has multiple dates as strings. With the following code, the search does not return anything. If I leave that field out, the search works just fine with the two other fields. I read that I should use CONTAINS with multivalue fields but then I got query not understandable.
I've tried the back-end field as a date field and as a text field and tested all kinds of query combinations and date formats but no luck. Any help is really appreciated.
This is the search button code:
var query = new Array("");
var cTerms = 0;
// Field 1
var search01 = getComponent("searchcustomReservationField01").getValue();
if (#Contains(#Text(search01),"any city")){"";}
else {query[cTerms++] = '[customReservationField01]="' + search01 +'"'};
// Field 2
var search02 = getComponent("searchcustomReservationField02").getValue();
if (#Contains(#Text(search02),"any city")){"";}
else {query[cTerms++] = '[customReservationField02]="' + search02 + '"'};
// Date 1
var formatter = new java.text.SimpleDateFormat("d.M.yyyy");
query[cTerms++] = 'FIELD freeDaysPool = ' + formatter.format(getComponent("searchcustomDateField01").getValue());
// if query is still empty, we fill it with asterisk
if(query == "" || query == null){
query[cTerms++] = "*";
}
// make all as string
qstring = query.join(" AND ").trim();
sessionScope.searchString = qstring;
It will return query as:
[customReservationField01]="Oslo" AND [customReservationField02]="Oslo" AND FIELD freeDaysPool = 6.2.2015
AFAIK date values in formulas (and a query is a formula) have to be noted like
[06.02.2015]
to compare them. Just try to use your formular in the Notes Client to do a fulltext search. If you get results and no errors you found the correct format. That's at least the way I test queries as I'm not able to remind the syntax for years :-D
Thank you for all the help! Seems that Domino keeps the field type as date field even if you change it back to text field (noticed that from the notes FTsearch). I created completely new text field and added the days as strings in dd.MM.yyyy format. I also search them as strings and it works fine.
The changed code bit now looks like this:
// Date 1
var formatter = new java.text.SimpleDateFormat("dd.MM.yyyy");
query[cTerms++] = '[freeDays] CONTAINS "' + formatter.format(getComponent("searchcustomDateField01").getValue())+'"';

Using string in place of property name (LINQ)

I have been able to get the values from tables using linq.
var q=(from app in context.Applicant
where app.ApplicantName=="")
Now what I want is this:
var q=(from app in context.Applicant
where app.stringIhave =="") // so instead of column name I have string which has same name as column.
Is it possible to specify string in Select as this is not sure what I will get in each case, I need different data all the time.
Is it possible to do so?
If no, then I will figure out something else.
Update
I have a GlobalString, which holds the column name of a table.
So when I query that table, I only specify from string which column value I want to get:
var q=(from app in context.Applicants
where app.ID==1013
select GlobalString //which is specifying that I want to get value from which column, as column name is not fixed.
//where GlobalString can have values like: app.FirstName..app.LastName etc
Update1:
var q = context.Applicants.Select("new(it.ApplicantFirstName as FirstName, it.ApplicantLastName as LastName)");
Error Message:
The query syntax is not valid. Near keyword 'AS'
You can use Dynamic Linq (available from NuGet) for that:
var q = context.Applicant.Where(app.stringIhave + " = #0", "");
for select you can try something like this
var q = context.Applicant.Select("new(it.FirstName as FirstName, it.LastName as LastName)");
so you only need construct string for that format

Resources