Perl Elastic query broken after upgrade from 2.4 to 5 - perl

As the title suggests, I am upgrading to ES5. My original ES query looked like:
my $response = $elastic->do_request_new(
{
query => {
filtered => {
filter => {
or => [
{ term => { _type => { value => "some_val1" } } },
{ term => { _type => { value => "some_val2" } } },
]
},
query => {
query_string => {
query => $qstring,
rewrite => "scoring_boolean",
analyze_wildcard => "true",
}
}
}
},
sort => [ qw(_score) ],
size => 50,
},
);
My updated looks like:
my $response = $elastic->do_request_new(
{
query => {
bool => {
should => [
{ term => { _type => { value => "some_val1" } } },
{ term => { _type => { value => "some_val2" } } },
],
must => {
query_string => {
query => $qstring,
rewrite => "scoring_boolean",
analyze_wildcard => "true",
}
}
}
},
sort => [ qw(_score) ],
size => 50,
},
);
However, upon searching for exact strings in my elastic database, I am returning zero results:
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 0,
"max_score" : null,
"hits" : [ ]
}
}
Any ideas about what might be happening? My guess is I have my query structure wrong. Thanks!

Update: The following fixed query:
my $response = $elastic->do_request_new(
{
query => {
bool => {
must => [
{
query_string => {
query => $qstring,
rewrite => "scoring_boolean",
analyze_wildcard => "true",
},
}
],
filter => {
bool => {
should => [
{ term => { _type => { value => "some_val1" } } },
{ term => { _type => { value => "some_val2" } } },
],
},
},
},
},
sort => [ qw(_score) ],
size => 50,
},
);

Related

How do I write a MongoDB $exists query in Perl?

db.getCollection('Subscriber').find({$and:[{"registerFrom":{$exists:false}},{"googleRegistrationId":{$exists:true}},{"isGuest":"false"}]})
how to write the above query in Perl please help this.I am getting different results on this when execute on perl
i have written like this in perl
my $Subscriber2 = $Subscriber->find({'$and' =>[{dateOfJoining => {'$gt' => $date}},{registerFrom => { '$exists' => 'false'}},{googleRegistrationId => {'$exists' => 'true'}},{isGuest => 'false'}]})->fields({ _id => 1,streamzCampaigns => 1});
I am not getting the same results as when executing in perl.How to use $exits of mongoDB in Perl.Please help on this one.
The two suspicious bits I see are that you've quoted "true" and "false" -- which make those strings, not boolean values -- and I wonder what you're using for $date, since you don't have that in your shell example.
Here is what you wrote, formatted nicely:
my $Subscriber2 = $Subscriber->find(
{
'$and' => [
{ dateOfJoining => { '$gt' => $date } },
{ registerFrom => { '$exists' => 'false' } },
{ googleRegistrationId => { '$exists' => 'true' } },
{ isGuest => 'false' }
]
}
)->fields( { _id => 1, streamzCampaigns => 1 } );
For the booleans, you should use the boolean.pm module:
use boolean;
my $Subscriber2 = $Subscriber->find(
{
'$and' => [
{ dateOfJoining => { '$gt' => $date } },
{ registerFrom => { '$exists' => false } },
{ googleRegistrationId => { '$exists' => true } },
{ isGuest => false }
]
}
)->fields( { _id => 1, streamzCampaigns => 1 } );

add a event listener when there is a post request for a specific schema in mongoose

I have two schemas
var customerSchema = mongoose.Schema( {
'joined' : { 'type' : Date, 'required' : true, 'default' : '01/01/1900' },
'fname' : { 'type' : String, 'required' : true, 'default' : '' },
'lname' : { 'type' : String, 'required' : true, 'default' : '' },
'city' : { 'type' : String, 'required' : true, 'default' : '' },
'orderTotal' : { 'type' : Number },
'orders' : [ { 'type' : mongoose.Schema.Types.ObjectId, 'ref' : 'orders' } ]
} );
var orderSchema = mongoose.Schema( {
'product' : { 'type' : String, 'required' : true },
'cost' : { 'type' : Number, 'required' : true },
'quantity' : { 'type' : Number, 'required' : true },
'total' : { 'type' : Number, 'required' : true },
'customer' : { 'type' : mongoose.Schema.Types.ObjectId, 'ref' : 'customers' }
} );
what I want to do is to add an order and then update the customerSchema orders field. So I did this:
exports.addCustomerOrder = function ( request, reply ) {
var total = request.payload.productQuantity * request.payload.productCost;
var order = new OrderSchema( {
'product' : request.payload.productName,
'cost' : request.payload.productCost,
'quantity' : request.payload.productQuantity,
'total' : total
} ).save( function( err, order ) {
if ( err ) {
return reply( {
'statusCode' : '500',
'error' : err,
'message' : 'Failed to add order'
} );
}
CustomerSchema.update( { '_id' : request.params.id },
{ '$push' : { 'orders' : order._id } },
{ 'upsert' : true },
function( err ) {
if ( err ) {
return reply( {
'statusCode' : '500',
'error' : err,
'message' : 'Failed to add order'
} );
}
reply( order );
} );
} );
};
Although it's working, I feel that what I have done here is inefficient. Is there something i'm missing to fully optimize my code? Like adding a event listener for orderSchema for example when I have added a new order it will automatically add the id to the customer rather than chaining two api request.
Today I learned about post hooks! So instead of chaining two queries at the same time, I have this sort of event listener when making a post request with my OrderSchema.
OrderSchema.post( 'save', function ( next ) {
var Customer = Mongoose.model( 'Customer' );
var conditions = {
'_id' : this.customerId
};
var options = {
'upsert' : true
};
var update = {
'$push' : {
'orders' : this._id
}
};
Customer.update( conditions, update, options, function ( err ) {
if ( err ) {
throw new Error( err );
}
} );
} );

How can i update the ids field?

Unfortunately, I cannot use positional operators since there is a bug that doesn't allow deeper than 1 embedded document: https://jira.mongodb.org/browse/SERVER-831
So this wont work (using the Mongodb Ruby driver):
stat_profile.update({ profile_id: profile.id, providers: { '$elemMatch' => { provider_name: 'foo', dates: { '$elemMatch' => { date: 20130911, relationships: { '$elemMatch' => { relationship_type: 'friend' } } } } } } },
{ '$set' => { 'providers.$.dates.$.relationships.$.ids' => [1,2,3] } })
Given the following collection. Relationships is embedded in dates, dates is embedded in providers.
How do I update the ids field?
{
"_id" => BSON::ObjectId('523048983858f61767000008'),
"profile_id" => 3,
"providers" => [
[0] {
"provider_name" => "foo",
"dates" => [
[0] {
"date" => 20130911,
"relationships" => [
[0] {
"relationship_type" => "acquaintance",
"count" => 0
},
[1] {
"relationship_type" => "friend",
"count" => 0,
"males_count" => 0,
"females_count" => 0,
"top_ten_countries" => [],
"ids" => []
}
]
}
]
}
]
}

perl mongodb complex structure update

I have this structure:
{
"user" => "xxxx",
"position" =>
{
"A1" => { "state" => 'It', region=>"LOM" etc etc..},
"A2" => { .... },
"A3" => { .... },
....
"An" => { .. }
}
}
insert is ok. but update return this error:
not a reference at /usr/local/lib/perl/5.12.4/MongoDB/Collection.pm line 376
My update is:
$tbl->update({
{ _id => MongoDB::OID->new(value => "$id") },
{ '$set' =>
{
"position" =>
{
"A1" => { "state" => "En" }
}
}
}
});
Where I wrong?
Thks!
I check syntax of update source of MongoDB::Collection
syntax update
update (\%criteria, \%object, \%options?)
inside MongoDB::Collection method update
sub update {
my ($self, $query, $object, $opts) = #_;
...
}
but you pass only 1 parameter.
$tbl->update(
{ # 1st anonymous hash
{ _id => MongoDB::OID->new(value => "$id") },
{ '$set' => {
"position" => {
"A1" => { "state" => "En" }
}
}
}
});
So I advice you figure out with passed parameters to method update.

dereferencing data from multiple hash and array data structure in perl

Trying to extract data from detailed -> doc -> params -> parameters -> name in following DoxyDocs1.pm file; also including sample of script that extracts some data, but having trouble extracting params -> parameters -> name. Uncomment commented sections to see data.
#!/bin/perl
use Data::Dumper;
use warnings;
require "DoxyDocs1.pm";
print "API Content Analyzer\n";
&GenerateClassInfo($doxydocs->{classes});
sub GenerateClassInfo()
{
my ($classes) = #_;
foreach my $class (#$classes) {
print "\nClass name is: $class->{name}\n";
foreach my $pubmeth (#{$class->{public_methods}->{members}}) {
print "\n" if exists $pubmeth->{name};
print "\tpublic methods include: $pubmeth->{name}\n";
my ($key, $pmcontent) = each (#{$pubmeth->{detailed}->{doc}});
print "\t\tdescription: $pmcontent->{content}\n" if exists $pmcontent->{content};
# foreach my $pmp (#{$pubmeth->{detailed}->{doc}}) {
# print "\t\t";
# print Dumper($pmp);
# }
print "\t\tkind: $pubmeth->{kind}\n";
print "\t\ttype: $pubmeth->{type}\n" if exists $pubmeth->{type};
}
foreach my $privmeth (#{$class->{private_methods}->{members}}) {
print "\n" if exists $privmeth->{name};
print "\tprivate methods include: $privmeth->{name}\n";
my ($key, $pmcontent) = each (#{$privmeth->{detailed}->{doc}});
print "\t\tdescription: $pmcontent->{content}\n" if exists $pmcontent->{content};
# foreach my $info (#{$privmeth->{detailed}->{doc}}) {
# print "\t\t";
# print Dumper($info);
# }
print "\t\tkind: $privmeth->{kind}\n";
print "\t\ttype: $privmeth->{type}\n" if exists $privmeth->{type};
}
}
}
Example DoxyDocs1.pm file
$doxydocs=
{
classes => [
{
name => 'Panoply::Composite',
public_methods => {
members => [
{
kind => 'function',
name => 'addChild',
virtualness => 'non_virtual',
protection => 'public',
static => 'no',
brief => {},
detailed => {
doc => [
{
type => 'text',
content => 'Add a child to the container '
},
params => [
{
parameters => [
{
name => 'child'
}
],
doc => [
{
type => 'text',
content => 'is the child element to add'
}
]
}
]
]
},
type => 'void',
const => 'no',
volatile => 'no',
parameters => [
{
declaration_name => 'child',
type => 'Ptr'
}
]
},
{
kind => 'function',
name => 'operator<',
virtualness => 'non_virtual',
protection => 'public',
static => 'no',
brief => {},
detailed => {
doc => [
{
type => 'text',
content => 'Less than operator'
},
{
type => 'parbreak'
},
params => [
{
parameters => [
{
name => 'rval'
}
],
doc => [
{
type => 'text',
content => 'The '
},
{
type => 'url',
link => 'classPanoply_1_1Package',
content => 'Package'
},
{
type => 'text',
content => ' against which we are comparing this one. '
}
]
}
],
{
return => [
{
type => 'text',
content => 'true if this.packageID < rval.packageID, false otherwise.'
}
]
}
]
},
type => 'bool',
const => 'yes',
volatile => 'no',
parameters => [
{
declaration_name => 'rval',
type => 'const Composite &'
}
]
},
]
},
private_methods => {
members => [
{
kind => 'function',
name => 'addChild',
virtualness => 'virtual',
protection => 'private',
static => 'no',
brief => {},
detailed => {
doc => [
{
type => 'text',
content => 'Add a child to the container '
},
params => [
{
parameters => [
{
name => 'child'
}
],
doc => [
{
type => 'text',
content => 'is the child element to add '
}
]
},
{
parameters => [
{
name => 'parent'
}
],
doc => [
{
type => 'parbreak'
},
{
type => 'text',
content => 'is this own parent, except in weak pointer format to avoid a memory leak'
}
]
}
]
]
},
type => 'virtual void',
const => 'no',
volatile => 'no',
parameters => [
{
declaration_name => 'child',
type => 'Ptr'
},
{
declaration_name => 'parent',
type => 'Ptr'
}
]
},
]
},
}
]
};
1;
You said you wanted
detailed -> doc -> params -> parameters -> name
but that's missing many indexes. Which doc, param and parameters do you want?
detailed -> doc -> ??? -> params -> ??? -> parameters -> ??? -> name
The syntax is:
$member->{detailed}->{doc}->[$i]->{params}->[$j]->{parameters}->[$k]->{name}
Or for short:
$member->{detailed}{doc}[$i]{params}[$j]{parameters}[$k]{name}
If you want to loop over every doc, params, parameter, you can use:
my $docs = $member->{detailed}{doc};
for my $doc (#$docs) {
my $params = $doc->{params};
for my $param (#$params) {
my $parameters = $param->{parameters};
for my $parameter (#$parameters) {
...
}
}
}
(Why is doc singular and params and parameters plural??? Why do params have parameters???)