Problem with embeded document query, when building query dynamically - mongoid

I'm trying to dynamically build a query where one can query an embedded document but it fails.
If I, however, copy the content of the query and try it works.
0> query
=> {:"properties.account_id"=>"5bd046d21d41c82e7c000004"}
0> Collection.where(query).to_a
=> []
0> Collection.where({:"properties.account_id"=>"5bd046d21d41c82e7c000004"}).to_a
=> [#<Collection _id: 5bd046d21d41c82e7c000006, created_at: 2018-10-24 10:17:54 UTC, updated_at: 2018-10-24 10:17:54 UTC, properties: {"account_id"=>"5bd046d21d41c82e7c000004"}>]
0> Collection.where(:"properties.account_id"=>"5bd046d21d41c82e7c000004").to_a
=> [#<Collection _id: 5bd046d21d41c82e7c000006, created_at: 2018-10-24 10:17:54 UTC, updated_at: 2018-10-24 10:17:54 UTC, properties: {"account_id"=>"5bd046d21d41c82e7c000004"}>]
And I have tried without colon
0> query
=> {"properties.account_id"=>"5bd049651d41c872d2000004"}
0> Collection.where(query).to_a
=> []
0> Collection.where({"properties.account_id"=>"5bd049651d41c872d2000004"}).to_a
=> [#<Collection _id: 5bd049651d41c872d2000006, created_at: 2018-10-24 10:28:53 UTC, updated_at: 2018-10-24 10:28:53 UTC, properties: {"account_id"=>"5bd049651d41c872d2000004"}>]
The explain data seems fine as well
{
"queryPlanner" => {
"plannerVersion" => 1, "namespace" => "db_testing.coll_test", "indexFilterSet" => false, "parsedQuery" => {
"properties.account_id" => {
"$eq" => "5bd04bf91d41c8d153000004"
}
}, "winningPlan" => {
"stage" => "COLLSCAN", "filter" => {
"properties.account_id" => {
"$eq" => "5bd04bf91d41c8d153000004"
}
}, "direction" => "forward"
}, "rejectedPlans" => []
}, "executionStats" => {
"executionSuccess" => true, "nReturned" => 0, "executionTimeMillis" => 1, "totalKeysExamined" => 0, "totalDocsExamined" => 2, "executionStages" => {
"stage" => "COLLSCAN", "filter" => {
"properties.account_id" => {
"$eq" => "5bd04bf91d41c8d153000004"
}
}, "nReturned" => 0, "executionTimeMillisEstimate" => 0, "works" => 4, "advanced" => 0, "needTime" => 3, "needFetch" => 0, "saveState" => 0, "restoreState" => 0, "isEOF" => 1, "invalidates" => 0, "direction" => "forward", "docsExamined" => 2
}, "allPlansExecution" => []
}, "serverInfo" => {
"host" => "ubuntu", "port" => 27017, "version" => "3.0.15", "gitVersion" => "b8ff507269c382bc100fc52f75f48d54cd42ec3b"
}
}
Any ideas?

Related

Perl generating hash of complex records

The big problem that I can't seem to figure out.
I need to input into this complex hash (array?):
my $raterequest =
{
Shipment =>
{
Shipper =>
{
(static data here)
},
ShipTo =>
{
(static data here too)
},
Package =>
[
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
},
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
}
],
}
};
What I need to input is everything inside the Package array.
I have an LoH that generates an output like this:
my %carton_specs =
(
25 => {
boxQty => 25,
boxWt => 4,
boxNo => 2
},
50 => {
boxQty => 50,
boxWt => 8,
boxNo => 17
},
);
Where I need to repeat the anonymous array inside Package
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
},
times the number returned from $boxNo. The only variable that changes in that is the Weight => $boxWt
Please excuse anything that I might have named wrong. I have been fighting with this for 2 days and my head is exploding.
It sounds to me like you are looking for push plus the information from perlreftut (plus maybe the .. range operator). I hope I understood your specifications correctly:
use warnings;
use strict;
use Data::Dump;
my $raterequest = {
Shipment => {
Package => [ ],
} };
my %carton_specs = (
25 => { boxQty => 25, boxWt => 4, boxNo => 2 },
50 => { boxQty => 50, boxWt => 8, boxNo => 17 },
);
for my $carton (sort keys %carton_specs) {
for ( 1 .. $carton_specs{$carton}{boxNo} ) {
push #{ $raterequest->{Shipment}{Package} }, {
PackagingType => {
Code => '02',
Description => 'Package',
},
PackageWeight => {
UnitOfMeasurement => { Code => 'LBS' },
Weight => $carton_specs{$carton}{boxWt},
},
};
}
}
dd $raterequest;
Output:
{
Shipment => {
Package => [
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 4 },
PackagingType => { Code => "02", Description => "Package" },
},
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 4 },
PackagingType => { Code => "02", Description => "Package" },
},
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 8 },
PackagingType => { Code => "02", Description => "Package" },
},
# ... omit 16 repetitions of the previous hashref ...
],
},
}

Spliting hash key containing of arrays to another keys

I have a problem with my ruby script. I don't know how to convert a hash
g = { ["name1", "name2"] => [{ "email" => "adam#adam.pl" }],
["name3", "name4"] => [{ "email" => "ewa#ewa.pl" }],
["name5", "name6", "name7", "name8"] => [{ "email" => "ala#ala.pl" }] }
to a hash:
x = { "name1" => [{ "email" => "adam#adam.pl" }],
"name2" => [{ "email" => "adam#adam.pl" }],
"name3" => [{ "email" => "ewa#ewa.pl" }],
"name4" => [{ "email" => "ewa#ewa.pl" }],
"name5" => [{ "email" => "ala#ala.pl" }],
"name6" => [{ "email" => "ala#ala.pl" }],
"name7" => [{ "email" => "ala#ala.pl" }],
"name8" => [{ "email" => "ala#ala.pl" }] }
I need to split the keys e.g. ["name1", "name2"] and put them as a keys of its value "name1" => [{ "email" => "adam#adam.pl" }], "name2" => [{ "email" => "adam#adam.pl" }].
Can you help me with this?
This is you can try something like it to get the result like
h = Hash[*g.map { |keys, value| keys.map {|key| [key,value]} }.flatten]
Which gives us a Hash
{ "name1" => { "email" => "adam#adam.pl" },
"name2" => { "email" => "adam#adam.pl" },
"name3" => { "email" => "ewa#ewa.pl" },
"name4" => { "email" => "ewa#ewa.pl" },
"name5" => { "email" => "ala#ala.pl" },
"name6" => { "email" => "ala#ala.pl" },
"name7" => { "email" => "ala#ala.pl" },
"name8" => { "email" => "ala#ala.pl" } }
In the above value is also hash format not in array. If its not required then this can work for you
Try this:
g.each_with_object({}) do |(k, v), obj|
k.each { |e| obj[e] = v }
end
Performance comparison with other solution:
# user system total real
# each_with_object...
# separate_keys1(1_000_000 times): 9.765000 0.000000 9.765000 ( 9.908535)
# Hash[]...
# separate_keys2(1_000_000 times): 16.505000 0.016000 16.521000 ( 16.725911)

saving some fields as null but they do have data

I´m trying to insert a new record, but it´s not saving fields: numAndares, numAptos and numTipo. Save them as null.
'condominio_id' and 'nome' are saving correctly.
My newEntity before and after save:
\src\Controller\CondominiosController.php (line 142)
object(App\Model\Entity\Torre) {
'condominio_id' => (int) 59,
'numAndares' => (int) 0,
'numAptos' => (int) 11,
'numTipo' => (int) 0,
'nome' => (int) 1,
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'condominio_id' => true,
'numAndares' => true,
'numAptos' => true,
'numTipo' => true,
'nome' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Torres'
}
\src\Controller\CondominiosController.php (line 146)
object(App\Model\Entity\Torre) {
'condominio_id' => (int) 59,
'numAndares' => (int) 0,
'numAptos' => (int) 11,
'numTipo' => (int) 0,
'nome' => (int) 1,
'id' => (int) 44,
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Torres'
}
When I save:
$torre = $torreTable->newEntity();
$torre->condominio_id = $condominio->id;
$torre->numAndares = 0;
$torre->numAptos = 11;
$torre->numTipo = 0;
$torre->nome = $x+1;
debug($torre);
if ($torreTable->save($torre)) {
debug($torre);
Any helpl?

CakePHP filter a deep associated find

I have a deep associated find and one association is retrieving too many none related records for modules_employees.
I should see only one record for modules_employees under the course_modules but it retrieves many because they can be many with course_modules_id but only one with courses_employee_id.
The modules_employees table
'id' => (int) 18,
'courses_employee_id' => (int) 31,
'course_module_id' => (int) 7,
'completed_on' => null,
CoursesEmployee->course->course_modules->modules_employees
CoursesEmployeesController.php
public function player($id = null)
{
$coursesEmployee = $this->CoursesEmployees->get($id, [
'contain' =>
[
'Employees',
'Courses',
'CourseModules',
'Courses.CourseModules',
'Courses.CourseModules.ModulesEmployees',
'Courses.CourseFiles'
]
]);
$this->set('coursesEmployee', $coursesEmployee);
debug($coursesEmployee);
$this->set('_serialize', ['coursesEmployee']);
}
The current find object, you will see one of the course_modules has two modules_employees when I should have one.
object(App\Model\Entity\CoursesEmployee) {
'id' => (int) 31,
'employee_id' => (int) 3,
'course_id' => (int) 3,
'course_module_id' => (int) 7,
'course_module' => object(App\Model\Entity\CourseModule) {
'id' => (int) 7,
'course_id' => (int) 3,
'name' => 'Module 2',
},
'course' => object(App\Model\Entity\Course) {
'id' => (int) 3,
'name' => 'Treacys Hotel Induction Training',
'course_files' => [
(int) 0 => object(App\Model\Entity\CourseFile) {
'id' => (int) 2,
'name' => 'Manual_Handling_doc.txt',
'type' => 'doc',
}
],
'course_modules' => [
(int) 0 => object(App\Model\Entity\CourseModule) {
'id' => (int) 6,
'course_id' => (int) 3,
'name' => 'Module 1',
'module_order' => (int) 1,
'modules_employees' => [
(int) 0 => object(App\Model\Entity\ModulesEmployee) {
'id' => (int) 1,
'courses_employee_id' => (int) 0,
'course_module_id' => (int) 6,
'started_on' => object(Cake\I18n\Time) {
'time' => '2015-09-08T04:16:16+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'completed_on' => object(Cake\I18n\Time) {
'time' => '2015-09-09T08:22:16+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'completed' => true,
'deleted' => null,
'[new]' => false,
'[accessible]' => [
'employee_id' => true,
'module_id' => true,
'started_on' => true,
'completed_on' => true,
'completed' => true,
'employee' => true,
'module' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'ModulesEmployees'
}
],
'[repository]' => 'CourseModules'
},
(int) 1 => object(App\Model\Entity\CourseModule) {
'id' => (int) 7,
'course_id' => (int) 3,
'name' => 'Module 2',
'module_order' => (int) 2,
'modules_employees' => [
(int) 0 => object(App\Model\Entity\ModulesEmployee) {
'id' => (int) 2,
'courses_employee_id' => (int) 31,
'course_module_id' => (int) 7,
'started_on' => object(Cake\I18n\Time) {
'time' => '2015-09-17T00:00:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'completed_on' => null,
'[repository]' => 'ModulesEmployees'
},
(int) 1 => object(App\Model\Entity\ModulesEmployee) {
'id' => (int) 18,
'courses_employee_id' => (int) 32,
'course_module_id' => (int) 7,
'started_on' => object(Cake\I18n\Time) {
'time' => '2015-09-17T00:00:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
},
'completed_on' => null,
'[repository]' => 'ModulesEmployees'
}
],
'[repository]' => 'CourseModules'
},
],
},
'employee' => object(App\Model\Entity\Employee) {
'id' => (int) 3,
'user_id' => (int) 4,
},
'[repository]' => 'CoursesEmployees'
}
You should look into matching
http://book.cakephp.org/3.0/en/orm/query-builder.html#filtering-by-associated-data
$query = $this->CoursesEmployees->findById($id)
->contain(['Your_Models_You_Wanna_Contain'])
->matching('Courses.CourseModules.ModulesEmployees', function ($q) use ($id) {
return $q->where(['courses_employee_id' => $id]);
});
if nothing matches then you wont get a CourseEmployee back aswell, if you would still need that you could also use contain:
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#passing-conditions-to-contain
$query = $this->CoursesEmployees->findById($id)->contain([
'Courses.CourseModules.ModulesEmployees' => function ($q) use ($id) {
return $q
->where(['courses_employee_id' => $id]);
}
]);

creating hash from variables to be used in json encode/decode perl

i'm trying to create a test module to test json encoding. i am having issues creating variables that will output correctly with the json encode/decode. if i use just the $cat_1 in the #cats array, it will work fine. however, using both, it prints out "HASH(..." as you can see below.
use strict;
use JSON;
use Data::Dump qw( dump );
my $cat_1 = {'name' => 'cat1', 'age' => '6', 'weight' => '10 kilos', 'type' => 'siamese'};
my $cat_2 = {'name' => 'cat2', 'age' => '10', 'weight' => '13 kilos', 'type' => 'siamese'};
my #cats;
push(#cats, $cat_1);
push(#cats, $cat_2);
my $dog_1 = {'name' => 'dog1', 'age' => '7', 'weight' => '20 kilos', 'type' => 'siamese'};
my $dog_2 = {'name' => 'dog2', 'age' => '5', 'weight' => '15 kilos', 'type' => 'siamese'};
my #dogs;
push(#dogs, $dog_1);
push(#dogs, $dog_2);
my $pets = {'cats' => #cats, 'dogs' => #dogs};
my $a = { 'id' => '123', 'name' => 'Joe Smith', 'city' => "Chicago", 'pets' => $pets };
my $json = JSON->new->allow_nonref;
my $encoded = $json->encode($a);
my $decoded = $json->decode( $encoded );
print "\ndump cat_1\n";
dump $cat_1;
print "\ndump cats\n";
dump #cats;
print "\n\nOriginal\n";
dump $a;
print "\n\n";
print "Encoded\n";
print $encoded;
print "\n\n";
print "Decoded\n";
dump $decoded;
print "\n\n";
output
dump cat_1
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" }
dump cats
(
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
{ age => 10, name => "cat2", type => "siamese", weight => "3 kilos" },
)
Original
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
Encoded
{"city":"Chicago","pets":{"HASH(0x1785f2d0)":{"weight":"3 kilos","name":"dog2","type":"siamese","age":"10"},"cats":{"weight":"10 kilos","name":"cat1","type":"siamese","age":"10"},"HASH(0x176c3170)":"dogs"},"name":"Joe Smith","id":"123"}
Decoded
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
This line
my $pets = {'cats' => #cats, 'dogs' => #dogs};
is a red flag. It's valid Perl, but it's not doing what you would expect. Perl will flatten your lists in this construction, so if #cats contains ($cat_1,$cat_2) and #dogs containts ($dog_1,$dog_2), your expression is parsed as
my $pets = { 'cats', $cat_1, $cat_2, 'dogs', $dog_1, $dog_2 };
which is like
my $pets = { 'cats' => $cat_1, $cat_2 => 'dogs', $dog_1 => $dog_2 }
with the hash references $cat_2 and $dog_1 getting stringified before being used as hash keys.
Hash values must be scalar values, not arrays. But array references are OK. Try:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
The problem is in the creation of $pets:
my $pets = {'cats' => #cats, 'dogs' => #dogs};
Is roughly equivalent to:
my $pets = {'cats', {name => 'cat1', ...}, {name => 'cat2', ...},
'dogs', {name => 'dog1', ...}, {name => 'dog2, ...} };
Which is the same as:
my $pets = {
'cats' => {name => 'cat1', ...},
{name => 'cat2'}, => 'dogs',
{name => 'dog1', ...}, => {name => 'dog2}
};
You want to use ArrayRefs:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
Which is:
my $pets = {
'cats' => [
{name => 'cat1', ...},
{name => 'cat2', ...},
],
'dogs' => [
{name => 'dog1', ...},
{name => 'dog2', ...},
],
};
Which is also how you could declare the whole data structure at once.

Resources