OrientDB: filter by entire embedded field value - orientdb

I'm to insert a record with embedded field in OrientDB and then to query for that record using filter:
insert into MyClass set embeddedField = {'#type': 'd', 'id': 1}
works well, and
select from MyClass
returns the record I've added. But when I add where with filter for embeddedField, I get no results:
select from MyClass where embdeddedField = {'#type': 'd', 'id': 1}
I thought that it could happen because Orient adds #version field into embedded document, so I tried to search with version:
select from MyClass where embdeddedField = {'#type': 'd', '#version': 0, 'id': 1}
But still got no results.
Question: Any idea how to filter embedded field by entire document? Without the need to filter explicitly by each field of embedded document:
select from MyClass
where embdeddedField.id = 1
and embdeddedField.field2 = val2
and embeddedField.field3 = val3
Because for several reasons I would like to pass the entire object as single query parameter:
select from MyClass where embdeddedField = ?

Thats because the provided Hash is transformed to an embedded class.
Perhaps take a look at the ActiveOrientWiki https://github.com/topofocus/active-orient/wiki/Relations
To explain:
Take a class base, there a document with two properties (schemaless)
and add existing documents to it
( 0..9 ).each do | b |
base_record= Base.create label: b, first_list: []
( 0..9 ).each {|c| base_record.first_list << FirstList.create( label: c ) }
end
INFO->CREATE VERTEX base CONTENT {"label":0,"first_list":[]}
INFO->CREATE VERTEX first_list CONTENT {"label":0}
INFO->update #136:0 set first_list = first_list || [#147:0] return after #this
then links are embedded and the record looks like
=> #<Base:0x00000000041a60e0 #metadata={:type=>"d", :class=>"base", :version=>11, :fieldTypes=>"first_list=z", :cluster=>129, :record=>1},
#attributes={:first_list=>["#149:1", "#150:1", "#151:1", "#152:1", "#145:2", "#146:2", "#147:2", "#148:2", "#149:2", "#150:2"], :label=>"1"}>
if you expand the list items, you can query for "#type"
If you add a document without rid, the same thing happens
( 0..9 ).each {|c| base_record.first_list << FirstList.new( label: c ) }
20.04.(12:53:59) INFO->update #130:2 set first_list = first_list || [{ #type: 'd' ,#class: 'first_list' ,label: 0 }] return after #this
INFO->CREATE VERTEX base CONTENT {"label":"c","first_list":[]}
'#130:2'.expand
=> #<Base:0x00000000043927a0 #metadata={:type=>"d", :class=>"base", :version=>11, :fieldTypes=>"first_list=z", :cluster=>130, :record=>2},
#attributes={:first_list=>["#151:12", "#152:12", "#145:13", "#146:13", "#147:13", "#148:13", "#149:13", "#150:13", "#151:13", "#152:13"], :label=>"c"}>
If you omit the class-name, only the scope of the rid's changes
INFO-> update #132:2 set first_list = first_list || { #type: 'd' ,label: 0 } return after #this
=> [#<Base:0x0000000003a26fb8 #metadata={:type=>"d", :class=>"base", :version=>3, :fieldTypes=>"first_list=z", :cluster=>132, :record=>2},
#attributes={:first_list=>["#3:0"], :label=>"d"}>]
In any case, a query for #type failes

Related

postgres add rows from array of objects

So what I'm trying to do is take an array of objects that are similar to the rows stored in the db (minus the id since that's auto-generated). However, I can't seem to figure it out. I'm using node-postgres. It would go something like this
const fooObj:Omit<Food, fooId> = {
// foodId omitted
a: 'a',
b: 'b',
c: 'c'
}
const fooArr = [...] // array of above Foo objects
const {rows} = pool.query(format(
`
INSERT INTO "foo" ("a","b","c")
VALUES // insert properties into column from each obj in fooArr //
RETURNING *
`,fooArr
))

Trigger to delete a field and add a prefix to other field

In my collection there is a document that can receive three fields, but I need to keep only two according to the values informed, for example I have fields A, B and C, depending on the value I do not need to record field B or C. I also need that A prefix is written in field A. I followed this documentation and created the function where I can read the fields, but I couldn't change or delete them. I used the onCreate event.
See my sample:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.testFields =
functions.firestore.document('documentos/{documentoId}/ocorrencias/{ocorrenciaId}').onCreate(async (snapshot, context) => {
const ocorrencia = snapshot.data();
//I can read the values
fieldA = ocorrencia.fieldA;
console.log('Field A: ', fieldA); //'Teste'
fieldB = ocorrencia.fieldB;
console.log('Field B: ', fieldB); //5
fieldC = ocorrencia.fieldC;
console.log('Field C: ', fieldC); //6
if(fieldB > FieldC){
//the C field does not need to be recorded
prefix = 'B';
}else{
//the B field does not need to be recorded
prefix = 'C';
}
//now I need to record the prefix next to FieldA
//my FieldA should look like this: 'CTeste'
});
You could do something like this:
if (fieldB > FieldC) {
//the C field does not need to be recorded
prefix = 'B';
ocorrencia.fieldC = null;
} else {
//the B field does not need to be recorded
prefix = 'C';
ocorrencia.fieldb = null;
}
//now I need to record the prefix next to FieldA
//my FieldA should look like this: 'CTeste'
ocorrencia.fieldA = prefix + fieldA;
functions.firestore.collection('ocorrencias').update(ocorrencia);
NOTE: The way your code is currently structured, it is performing 2 write calls to every record you create, one on the actual creation of the record, followed by the update call I suggested. This could generate some overhead on your system moving forward, or at least increase your number of write operations, which could be significant on billing, I would suggest you perform this check not in a cloud function, but in your front end.

pg-promise update where in custom array

How can the following postgresql query be written using the npm pg-promise package?
update schedule
set student_id = 'a1ef71bc6d02124977d4'
where teacher_id = '6b33092f503a3ddcc34' and (start_day_of_week, start_time) in (VALUES ('M', (cast('17:00:00' as time))), ('T', (cast('19:00:00' as time))));
I didn't see anything in the formatter namespace that can help accomplish this. https://vitaly-t.github.io/pg-promise/formatting.html
I cannot inject the 'cast' piece into the '17:00:00' value without it being considered part of the time string itself.
The first piece of the query is easy. It's the part after VALUES that i can't figure out.
First piece:
var query = `update schedule
set student_id = $1
where teacher_id = $2 and (start_day_of_week, start_time) in (VALUES $3)`;
var inserts = [studentId, teacherId, values];
I'm using this messiness right now for $3 (not working yet), but it completely bypasses all escaping/security built into pg-promise:
const buildPreparedParams = function(arr, colNames){
let newArr = [];
let rowNumber = 0
arr.forEach((row) => {
const rowVal = (rowNumber > 0 ? ', ' : '') +
`('${row.startDayOfWeek}', (cast('${row.startTime}' as time)))`;
newArr.push(rowVal);
});
return newArr;
};
The structure I am trying to convert into this sql query is:
[{
"startTime":"17:00:00",
"startDayOfWeek":"U"
},
{
"startTime":"16:00:00",
"startDayOfWeek":"T"
}]
Use CSV Filter for the last part: IN (VALUES $3:csv).
And to make each item in the array format itself correctly, apply Custom Type Formatting:
const data = [{
startTime: '17:00:00',
startDayOfWeek: 'U'
},
{
startTime: '16:00:00',
startDayOfWeek: 'T'
}];
const values = data.map(d => ({
toPostgres: () => pgp.as.format('(${startDayOfWeek},(cast(${startTime} as time))', d),
rawType: true
}));
Now passing in values for $3:csv will format your values correctly:
('U',(cast('17:00:00' as time)),('T',(cast('16:00:00' as time))

.Include in following query does not include really

var diaryEntries = (from entry in repository.GetQuery<OnlineDiary.Internal.Model.DiaryEntry>()
.Include("DiaryEntryGradeChangeLog")
.Include("DiaryEntryAction")
join diary in repository.GetQuery<OnlineDiary.Internal.Model.OnlineDiary>()
on entry.DiaryId equals diary.Id
group entry
by diary
into diaryEntriesGroup
select new { Diary = diaryEntriesGroup.Key,
DiaryEntry = diaryEntriesGroup.OrderByDescending(diaryEntry => diaryEntry.DateModified).FirstOrDefault(),
});
This query does not include "DiaryEntryGradeChangeLog" and "DiaryEntryAction" navigation properties, what is wrong in this query?
I have removed join from the query and corrected as per below, and still it populates nothing
var diaryEntries = from entry in repository.GetQuery<OnlineDiary.Internal.Model.DiaryEntry>()
.Include("DiaryEntryGradeChangeLog").Include("DiaryEntryAction")
.Where(e => 1 == 1)
group entry
by entry.OnlineDiary
into diaryEntryGroups
select
new { DiaryEntry = diaryEntryGroups.OrderByDescending(diaryEntry => diaryEntry.DateModified).FirstOrDefault() };
It will not. Include works only if the shape of the query does not change (by design). If you use this query it will work because the shape of the query is still same (OnlineDiary.Internal.Model.DiaryEntry):
var diaryEntries = (from entry in repository.GetQuery<OnlineDiary.Internal.Model.DiaryEntry>()
.Include("DiaryEntryGradeChangeLog")
.Include("DiaryEntryAction");
But once you use manual join, grouping or projection (select new { }) you have changed the shape of the query and all Include calls are skipped.
Edit:
You must use something like this (untested) to get related data:
var diaryEntries = from entry in repository.GetQuery<OnlineDiary.Internal.Model.DiaryEntry>()
group entry by entry.OnlineDiary into diaryEntryGroups
let data = diaryEntryGroups.OrderByDescending(diaryEntry => diaryEntry.DateModified).FirstOrDefault()
select new {
DiaryEntry = data,
GradeChangeLog = data.DiaryEntryGradeChangeLog,
Action = data.DiaryEntryAction
};
or any similar query where you manually populate property for relation in projection to anonymous or unmapped type.

Zend_Db query and row count without pulling back everything up front

I've created my select:
$select = $zdb->select()
->from(array("b" => "blogs"),
array("id", "active", "updated_by", "title", "synopsis", "create_date", "body"))
->join(array("u" => "users"),
'b.updated_by = u.id',
array("first_name", "last_name"))
->where("u.blogger = ?", 1)
->where("b.publish_date > ?", '2020-01-01')
->where("b.active = ?", 1)
->group("b.id")
->order("b.publish_date DESC")
->limit(5);
and I want to pull the data back a row at a time:
$stmt = $db->query($select);
while ($asset = $stmt->fetch()) {
// do stuff
}
How can I check to make sure that there are rows, without returning the entire resultset?
Using the select you already have, something like that should help you parse every entry
$rows = $zdb->fetchAll($select);
foreach($rows as $row){
...
}
To get the values you just have to do $row['fieldName'] where fieldName is the name of the field in your database