Drupal date range indexing with Apache Solr - date

i am using these drupal modules
search_api
search_api_solr
date_range_formatter
views
and in fact many other modules to get my Solr / Drupal project going to index ~100000 nodes of content.
The setup is working great, BUT i need to get search results from the Solr for a date range field and this is where i am stuck.
Somehow i am stuck with setting up the correct operator "between" and "not between" and using "<=" or ">=" is causing trouble here.
I can't get my Solr-query like
field[1 TO *] AND field[* TO 10]
to work.
One content type can have multiple date ranges when available for searching.
The user can search for a start date and an end date. The daterange should match inside each individual daterange of the indexed entity type.
Let's say it is valid from:
2015-10-01 to 2015-10-10
2015-11-01 to 2015-11-10
...
and so on.
To get me going and sort the problems the right way i need to know first:
What is the best practise to store a date range inside Drupal to index at the Solr side? Is a date range a good way or would is better to store a range with a value for each day individually like:
2015-10-01
2015-10-02
2015-10-03
...
What is the best for Solr to index a date range?
What field type inside Drupal would you suggest to store the values inside an entity type to be able to send it to Drupal?
I know i am not the first struggeling with this. Details can be found here:
https://www.drupal.org/node/1783746
but onfortunately none of these patches were error free to my setup. I tried all out to get this going. Now i am looking for any advice, sum ups or thoughts that might be helpful to track down my last bits of errors.
Any advice or idea is really appreciated.
Thanks.

This is not a step by step solution. I just want to give you an idea how to adapt this to your project and still stay compatible with search_api and search_api_solr:
One possible solution could be to store and index the dates from an entity in one field per date individually as
2015-10-01
2015-10-02
2015-10-03
...
after this use
function mymodule_search_api_views_query_alter(
view &$view,SearchApiViewsQuery &$query) {
...
}
}
to add missing query conditions like
AND field_name = 2015-10-01 (as timestamp)
AND field_name = 2015-10-02
AND field_name = 2015-10-03
to take care of all conditions.
I hope this is helpful to someone who is in need of a similar solution.

Related

MS Access use DATE() in a calculated field

I am using Microsoft Access 2016. I am trying to find out how many years exist from the current year until a future year. I have a column that is end_date. I am trying to create a calculated field that is essentially YEAR(end_date) - YEAR(current_year). I tried to use YEAR(DATE()) but DATE() is not allowed to be used in a calculated field apparently.
Is there no way to do a calculation like this?
Nope. Calculated fields are cached and static, so are NEVER allowed to contain ANY information that will change over time, due to system settings, or anything else that is not directly entered in that row.
However, you should not be using calculated fields anyway. See http://allenbrowne.com/casu-14.html, among many posts advocating for not using calculated fields.
Instead, use queries to do calculations. That way, you won't have any trouble using the current date, and won't have to deal with the possible errors and portability issues calculated fields come with.
I changed my thinking to calculate this in a form. It does not seem good practice to have a field in a DB that changes everyday.
In a form, you can use this expression as controlsource for a textbox:
=DateDiff("yyyy",Date(),[EndDate])
However, that return the difference in calendar years. To find the count of full years, use a function like AgeSimple and this expression:
=AgeSimple([EndDate])

How to get all missing days between two dates

I will try to explain the problem on an abstract level first:
I have X amount of data as input, which is always going to have a field DATE. Before, the dates that came as input (after some process) where put in a table as output. Now, I am asked to put both the input dates and any date between the minimun date received and one year from that moment. If there was originally no input for some day between this two dates, all fields must come with 0, or equivalent.
Example. I have two inputs. One with '18/03/2017' and other with '18/03/2018'. I now need to create output data for all the missing dates between '18/03/2017' and '18/04/2017'. So, output '19/03/2017' with every field to 0, and the same for the 20th and 21st and so on.
I know to do this programmatically, but on powercenter I do not. I've been told to do the following (which I have done, but I would like to know of a better method):
Get the minimun date, day0. Then, with an aggregator, create 365 fields, each has that "day0"+1, day0+2, and so on, to create an artificial year.
After that we do several transformations like sorting the dates, union between them, to get the data ready for a joiner. The idea of the joiner is to do an Full Outer Join between the original data, and the data that is going to have all fields to 0 and that we got from the previous aggregator.
Then a router picks with one of its groups the data that had actual dates (and fields without nulls) and other group where all fields are null, and then said fields are given a 0 to finally be written to a table.
I am wondering how can this be achieved by, for starters, removing the need to add 365 days to a date. If I were to do this same process for 10 years intead of one, the task gets ridicolous really quick.
I was wondering about an XOR type of operation, or some other function that would cut the number of steps that need to be done for what I (maybe wrongly) feel is a simple task. Currently I now need 5 steps just to know which dates are missing between two dates, a minimun and one year from that point.
I have tried to be as clear as posible but if I failed at any point please let me know!
Im not sure what the aggregator is supposed to do?
The same with the 'full outer' join? A normal join on a constant port is fine :) c
Can you calculate the needed number of 'dublicates' before the 'joiner'? In that case a lookup configured to return 'all rows' and a less-than-or-equal predicate can help make the mapping much more readable.
In any case You will need a helper table (or file) with a sequence of numbers between 1 and the number of potential dublicates (or more)
I use our time-dimension in the warehouse, which have one row per day from 1753-01-01 and 200000 next days, and a primary integer column with values from 1 and up ...
You've identified you know how to do this programmatically and to be fair this problem is more suited to that sort of solution... but that doesn't exclude powercenter by any means, just feed the 2 dates into a java transformation, apply some code to produce all dates between them and for a record to be output for each. Java transformation is ideal for record generation
You've identified you know how to do this programmatically and to be fair this problem is more suited to that sort of solution... but that doesn't exclude powercenter by any means, just feed the 2 dates into a java transformation, apply some code to produce all dates between them and for a record to be output for each. Java transformation is ideal for record generation
Ok... so you could override your source qualifier to achieve this in the selection query itself (am giving Oracle based example as its what I'm used to and I'm assuming your data in is from a table). I looked up the connect syntax here
SQL to generate a list of numbers from 1 to 100
SELECT (MIN(tablea.DATEFIELD) + levquery.n - 1) AS Port1 FROM tablea, (SELECT LEVEL n FROM DUAL CONNECT BY LEVEL <= 365) as levquery
(Check if the query works for you - haven't access to pc to test it at the minute)

Executing a Find Script with a range of dates as the criteria

Im trying to create a Find Script on two date selection fields (Drop Down calendars) that automatically run each time the field is updated/changed (I understand this part aka script triggers) and the report will show the results that contain dates listed between the range selected.
Please Keep in mind that I'm quite new to this so please correct me where you think I could improve is you find or see anything else that appears to be wrong. Anyways, here is the Layout for my report where the selection fields and results field are highlighted.
Here is the script code I've created and I'm trying to use.
"Pre Construction::Bid Date" ≥ "Bid Date Search::Start Date" & "Pre Construction::Bid Date" ≤ "Bid Date Search::Start Date"
Here is the error I get when I try to add/save this in/under the perform find -> specify dialog box.
Ive tried and set all the fields to use the exact same date layout and format (the xx/xx/xxxx) and ive still had no luck in created this type of search. Im hoping someone will be able to help me fix this or offer other solutions as to how I could go about creating this. Thank you all
There are two problems with your attempt:
First, you cannot use references to fields in a find request.
Next, to find records within a specified range, you must use the range operator (two or three periods).
Now, you could populate variables with the range boundaries and use these in the find request instead of the fields, but it is much more convenient to skip stored find requests altogether and do simply:
Enter Find Mode [ ]
Set Field [ Pre Construction::Bid Date; Bid Date Search::Start Date & ".." & Bid Date Search::End Date ]
Perform Find [ ]
Of course, we are assuming that the Start Date and End Date fields are global fields.

Tableau calculated field dates

I was trying to do a calculated field and I cannot get it to work right.
First I tried to duplicate what I did in access...
=DateDiff("d",[90 Days to Exp],[Expiration])
but that gives me an error
I did some research and found something that gave me valid calculations...
window_sum(datediff('day',
lookup(min([90 Days to Exp]), 0),
min([Expiration])))
that only shows 90 days which I already knew
I want to make sure it is doing a count down of days to "Expiration" so I changed it to...
window_sum(datediff('day',
lookup(min(NOW()), 0),
min([Expiration])))
also tried....
window_count(datediff('day',
lookup(min(NOW()), 0),
min([Expiration])))
still a valid calc but the numbers are way off.... I tried min and max with and without... and I still can't seem to get an accurate count down
Step back. Instead of giving us random pieces of code, explain what you're trying to achieve (what you expect as a result) and what your db looks like (for instance, what are the fields).
I'll give a solution to what I think you're trying to achieve on what I think you have as database.
I believe you have a database that each entry is a product that have an expiration date ([Expiration]). What I think you're trying to achieve is to know how many days are left until expiration date.
So, if you want to calculate this for each entry in your database, the formula should be:
DATEDIFF('day',NOW(),[Expiration])
It's very straight forward, you're calculating how many days there are between today and expiration date
I have no idea why you're using table calculations in your suggestions, but if this calculations should not be done for each entry (but rather for a collection of entries), then table calculations can be useful, but it's impossible to suggest anything if I don't understand precisely what you want

Zend_Search_Lucene and range search

I have a bunch of int key fields in my index and trying to do a simple range search like this:
`gender:1 AND height:[120 TO 180]`
This should give me male in the height range 120 to 180. But for some reason i get this exception:
`At least one range query boundary term must be non-empty term`
How would i debug this? Is it just Zend_Search_Lucene being buggy?
This is an open bug in the query parser of the Zend Framework. Created in december 2008 with high priority... and still unsolved.
First, you have to change default Analyzer to TextNum to allow number before finding
ZF2:
\ZendSearch\Lucene\Analysis\Analyzer\Analyzer::setDefault(new \ZendSearch\Lucene\Analysis\Analyzer\Common\TextNum\CaseInsensitive());
Second, your date field MUST be a keyword, not text.