mongoDB data filter by range - mongodb

I have one collection where I want to filter data based on a range.
Range will go like this:
Last week (last_week)
Last month (last_month)
Last quarter (last_quarter)
I want to take input as last_week or last_month or last_quarter and based upon the input given, I want to filter data from documents matching the criteria supplied.
Is it possible to build a criteria on the fly based upon the input given?

Yes, you can. Build your criteria like this,
query = {};
query.createdDate = {
$gt: last_week,
$lt: last_month,
};

Related

Mongo Atlas filter by date is not working

I am using the the following query to filter dates greater than the 25th of May, but it does not work. In the UI I chose the $match operator
{
query: {$date:{ $gte:ISODate('2022-05-25')}}
}
In fact in the resulting collection it returns also dates prior to the one that I have specified in the filter condition.
Can you point me to the exact query?

CouchDB filtering on key array

Given a CouchDb view that emits like this:
emit([doc.name, doc.date], doc)
How to filter on multiple doc.name values? Below doesn't seem to work.
keys=[["name1",{}],["name2",{}],["name3",{}]]
When you specify the keys parameter, you are specifying an exact match. Assuming you want a range query (every document with name="name1" no matter the date) then you need to query with a startkey and an endkey:
?startkey=["name1", ""]&endkey=["name1", {}]
And will have to repeat the query for each name.

How to query date saved as text in bad date format in mongoDB

I am very new to mongodb
I have a database with sale_date and the value is saved as text and the format is "dd:mm:yyyy". Now I want to query based on the date. Like I want to query the last month's entry.
I also have field sale_time and also saved as text and the format is "hh:mm" and I want to query the last hour's entry.
**I want to query from java and also from the mongo console.
One row of my collection:
{
"_id":112350,
"sale_date":"21.07.2011",
"sale_time":"18:50",
"store_id":"OK3889-45",
"region_code":45,
"product_id":"QKDGLHX5061",
"product_catagorie":53,
"no_of_product":1,
"price":1211.37,
"total_price":1211.37
}
I have million of entries. Now I want to find the entries for the month of July 2011 or hour from 18:00 to 19:00 in 21.07.2013.
You can query with a regex matching your results. You said format dd:mm:yyyy but the example looks like dd.mm.yyyy so I used that in examples
For example:
db.sales.find({sale_date: /..\.07\.2011/})
This will be ineficient since it can't use an index, but it will get the job done.
It would be better, if you stick with dates as strings to reverse the order to yyyy:mm:dd then you could use a anchored regex, which will hit an index like:
db.sales.find({sale_date: /2011\.07/})
For the hour query:
db.sales.find({sale_date: "21.07.2013", sale_time: {$gte: "18:00", $lt: "19:00"}})
There is no efficient and reliable way to query the for a date range you want given the date structure you have used. A regex style query would scan through the entire collection for example, and if you have millions of documents, that's not acceptable.
You could theoretically create a MapReduce to better structure the data into a new collection. But, that will be more work to maintain (as MapReduces aren't automatically updated, and may make other queries and data fetching involve more steps than you'd like).
Although, if you're willing to do that, I'd strongly suggest you instead just fix your data as I mentioned in my comment to be a standard YYYYMMDD. Even better, you may want to consider merging the time and would be to include the time stamp in the same field:
2013-07-21T14:30
If you don't though, you can still do the single date query reasonably (although you'd want to index both the date and time as a compound index):
db.sales.ensureIndex({ sale_date: 1, sale_time: 1})
Regarding the code, it's basically going to look like this:
BasicDBObject date = new BasicDBObject("sale_date", "21.07.2013");
BasicDBObject time = new BasicDBObject("sale_time",
new BasicDBObject("$gte", "18:00").
append("$lte", "19:00"));
BasicDBObject andQuery = new BasicDBObject();
List<BasicDBObject> obj = new ArrayList<BasicDBObject>();
obj.add(date);
obj.add(time);
andQuery.put("$and", obj);
cursor = coll.find(andQuery);

How can I sort a Meteor collection by time of insertion?

I am working on my first project using Meteor, and am having some difficulty with sorting.
I have a form where users enter aphorisms that are then displayed in a list. Currently the most recent aphorisms automatically display at the bottom of the list. Is there an easy way to have the most recent appear at the top of the list instead?
I tried:
Template.list.aphorisms = function () {
return Aphorisms.find({}, {sort: {$natural:1}});
};
And am stumped because the Meteor docs don't have many examples.
Assuming that the date_created is in a valid date format along with the timestamp, You should insert the parsed value of date_created using Date.parse() javascript function, which gives the number of milliseconds between January 1, 1970 and date value contained in date_created.
As a result of that, the most recently added record will contain greater value of date_created than the record inserted before it.
Now when fetching the records, sort the cursor in descending order of the date_created parameter as:
Aphorisms.find({}, {sort: {date_created: -1}});
This will sort records from newer to older.
I've found the following to be a cleaner solution:
Template.list.aphorisms = function () {
return Aphorisms.find().fetch().reverse();
};
Given that entire collection already exists in the reverse order that you would like, you can simply create an array of all the objects and reverse the order.

Search between two dates using Lucene.Net

In my Lucene.Net index, I have documents with a startDate field and an endDate field. Both fields store dates in yyyyMMdd format. How can I build a query that will return hits if today's date falls between those two dates?
startDateFieldValue < myTargetDate < endDateFieldValue
For example, if myTargetDate is 17760604, I'd want to get a document back that had a startDate field value of 10660101 and an endDate field value of 19990101.
The scenario is that I have a Lucene database with Lucene documents that represent particular building sites. Each site has a StartConstruction date and an EndConstruction date. My users will enter a specific date, and I want to find all properties that were currently under construction on that date.
Note: I'm working with Lucene.Net 1.9, a much older version, and my company can't upgrade (yet).
You can do this using a Range Query. Specifically, you can do this using a NumericRangeQuery. To do this begin by indexing your dates using a NumericField and adding them to your document like:
var df = new NumericField(Fields.AmendedDate);
df.SetIntValue(int.Parse(itemToIndex.startDate.ToString("yyyyMMdd")));
doc.Add(df);
You can make your indexing a little faster by reusing your NumericField across many documents see the documentation. With your dates all nicely indexed you are now ready to search across it. To do this we use a NumericRangeQuery:
var q = NumericRangeQuery.NewIntRange( Fields.AmendedDate,
int.Parse(SearchFrom.ToString("yyyyMMdd")),
int.Parse(SearchTo.ToString("yyyyMMdd")),
true, true);
This query can then be used to search or conjoined to an existing query like:
masterQuery.Add(q, BooleanClause.Occur.MUST);
Splitting your search in this way is a far faster proposition than using a textual term search due to the nature of how numeric fields are indexed. Also, your resolution (in this instance to day level) can be altered to give a better spread across your data (i.e. if you need to the hour, minute or second then add them to the string from most to least significant). The final point of this is that by using a query you ignore the filtering step of your search (it's a normal query, not a filter).
I'm not sure I phrased my question properly. I want to find out if a particular item was active between a start and an end date. The StartDate is stored in one Lucene field, the EndDate in another.
Here's the search snippet I used:
var searchableDate = DateTools.DateToString(dateToSearchFor, DateTools.Resolution.DAY);
var lowerRange = new RangeQuery(null, new Term("StartDate", searchableDate), true);
var upperRange = new RangeQuery(new Term("EndDate", searchableDate), null, true);
var activeTodayFilter = new BooleanQuery();
activeTodayFilter.Add(new BooleanClause(lowerRange, BooleanClause.Occur.MUST));
activeTodayFilter.Add(new BooleanClause(upperRange, BooleanClause.Occur.MUST));
return activeTodayFilter;
I found the solution in an old Lucene forum/newsgroup, but I'm afraid I don't remember the link.
If there's an easier/better way to write the query above, let me know.
You have to use a RangeQuery.
RangeQuery rq = new RangeQuery(new Term("date", "10660101"),new Term("date", "19990101") ,true);
In an up-to-date version you could use NumericFields/NumericRangeQuery for better performance.