QueryParser is great, but I would like to make a query myself, so I can filter results by a specified value (in this case restricting by epoch time after a certain value) My code looks like this, and compiles, and appears like it should work according to the perl source: my $query = $qp->parse_query($querystr); if ($datefilter) { my $filterepoch = time() - ($datefilter * 60 * 60 * 24); my $filterquery = Xapian::Query->new(OP_VALUE_GE,I_DATE,$filterepoch); $query = Xapian::Query->new(OP_FILTER,$query,$filterquery); } This appears to die on Xapian::Query->new with No matching function for overloaded 'new_Query' at /usr/local/lib/perl5/site_perl/Xapian.pm line 1282. I see in Xapian.pm where Xapian::Query attempts to call Xapianc::new_Query . Is there some other way I am supposed to do this? I should say that I am using xapian-bindings-1.4.4 which I compiled and installed myself. Thanks, - Alex Aminoff NBER
On Tue, Sep 12, 2017 at 04:47:52PM -0400, Alex Aminoff wrote:> my $filterepoch = time() - ($datefilter * 60 * 60 * 24); > my $filterquery > Xapian::Query->new(OP_VALUE_GE,I_DATE,$filterepoch);I think your issue here is that $filterepoch is a number rather than a string (a Perl scalar can have different representations internally). In t/valuerange.t this testcase works: | ok( $query = Xapian::Query->new(OP_VALUE_GE, 0, "two") ); But if I change that "two" to 2 then I get the same error you report. While such sensitivity to the actual current representation of a scalar isn't very Perl-ish, it does actually indicate a problem with your code - OP_VALUE_GE performs a *string* >= (like Perl's own "ge"), so if you give it variable width integers (like the above would if $filterepoch were silently coerced to a string) then you won't in general get the correct filtering - for example, "100" < "99". I'd suggest formatting as a fixed width string value (left padded with zeros or spaces) or packing into a big-endian binary value (e.g. pack("N", $filterepoch)) or using Xapian::sortable_serialise(). Xapian::sortable_serialise() is particularly useful with floating point values, but even with integers it produces fairly compact output (much better than a fixed width string).> I should say that I am using xapian-bindings-1.4.4 which I compiled and > installed myself.In case you missed the warning in the README: | Perl These Perl bindings are generated by SWIG, and are intended | to replace the hand-written Search::Xapian XS bindings. | The current API should be regarded as experimental - we plan | to review it, possibly make some changes and then declare it | stable early in the 1.4.x release series. [...] Sadly I've still not found time to sort that out. If you're happy to potentially have to tweak your code, the SWIG-based Perl bindings in 1.4.x certainly aren't a bad choice. But if you prefer something that's got a stable API, then Search::Xapian 1.2.x should work with xapian-core 1.4.x (its main downside is that it doesn't wrap the C++ API as completely as the SWIG-based bindings do). Cheers, Olly
On 9/12/2017 5:41 PM, Olly Betts wrote:> On Tue, Sep 12, 2017 at 04:47:52PM -0400, Alex Aminoff wrote: >> my $filterepoch = time() - ($datefilter * 60 * 60 * 24); >> my $filterquery >> Xapian::Query->new(OP_VALUE_GE,I_DATE,$filterepoch); > I think your issue here is that $filterepoch is a number rather than > a string (a Perl scalar can have different representations internally). > In t/valuerange.t this testcase works: > > | ok( $query = Xapian::Query->new(OP_VALUE_GE, 0, "two") ); > > But if I change that "two" to 2 then I get the same error you report. > > While such sensitivity to the actual current representation of a scalar > isn't very Perl-ish, it does actually indicate a problem with your code - > OP_VALUE_GE performs a *string* >= (like Perl's own "ge"), so if you give it > variable width integers (like the above would if $filterepoch were silently > coerced to a string) then you won't in general get the correct filtering > - for example, "100" < "99". > > I'd suggest formatting as a fixed width string value (left padded with > zeros or spaces) or packing into a big-endian binary value (e.g. > pack("N", $filterepoch)) or using Xapian::sortable_serialise().Huh. I was even vaguely aware of this problem, but expected to work on that later, after I got the code working first - I was figuring I would quickly see problematic search results (as you say, "100" < "99" and similar) once it was running. I guess it would be nice if the error message was more of a pointer to the problem. Xapian::Query has no perldoc. If I were to write some, and pass it in through a git pull request or some such mechanism, would that be helpful? - Alex> Xapian::sortable_serialise() is particularly useful with floating > point values, but even with integers it produces fairly compact output > (much better than a fixed width string). > >> I should say that I am using xapian-bindings-1.4.4 which I compiled and >> installed myself. > In case you missed the warning in the README: > > | Perl These Perl bindings are generated by SWIG, and are intended > | to replace the hand-written Search::Xapian XS bindings. > | The current API should be regarded as experimental - we plan > | to review it, possibly make some changes and then declare it > | stable early in the 1.4.x release series. [...] > > Sadly I've still not found time to sort that out. > > If you're happy to potentially have to tweak your code, the SWIG-based > Perl bindings in 1.4.x certainly aren't a bad choice. > > But if you prefer something that's got a stable API, then Search::Xapian > 1.2.x should work with xapian-core 1.4.x (its main downside is that it > doesn't wrap the C++ API as completely as the SWIG-based bindings do). > > Cheers, > Olly