OrientDB Nested JSON Insert - orientdb

I have a OrientDB question. For the statement
INSERT INTO Account CONTENT
{ name : 'Luca',
vehicles : {
#class : 'Vehicle',
type : 'Car',
model : 'Maserati',
isItTrue: false
}
}
I get a result (see screenshot), but the class/table 'Vehicle' does not contain any entries. Is this a valid result?
I expected that automatically some values are written into 'Vehicle' and connected to 'Account'. Only the column 'vehicles' from 'Account' contains JSON-Data.
Thank you for your response.
Best regards
Karo
Screenshot OrientDB

With your query you are inserting embedded data into Account, if you want to insert some data into Account and Vehicle, you should do it in different queries and then if you want you can connect them with an edge. See example:
create class Account extends v
create class Vehicle extends v
create class owns extends e
create property Account.name String
create property Vehicle.type String
create property Vehicle.model String
create property Vehicle.isItTrue BOOLEAN
insert into Account(name) values ("Luca")
insert into Vehicle(type, model, isItTrue) values ("Car", "Maserati", false)
create edge owns from (select from Account where name = "Luca") to (select from Vehicle where model = "Maserati")

Alternatively, if you are not looking to create edges and you just want a link from document to document, the below will give you desired results in single insert / transaction while still keeping your json structure for the linked record
create class Account
create class Vehicle
create property Account.vehicles embedded Vehicle
INSERT INTO Account set name = "luca", vehicles = [ {
"#type": "d",
"#class" : "Vehicle",
"type" : "Car",
"model" : "Maserati",
"isItTrue": false
}]

Related

How to join tables and get relative data from another table using nest js + typeorm?

I have table structure like this :
Admin can create another admin, and they can create Accounts. So In account table, I have add relationship like this :
#ManytoOne(()=> adminEntity, (Admin)=> admin.id)
created_by: String
Now I want to fetch all the account detail with admin's detail like this :
[{
name: "account 1",
created_by: "fa46-f456as-45f6sd-fads"
owner : <Admin Detail of created_by id above>
},
{
name: "account 2",
created_by: "f45sd6-4654fd-5f4asd6-f654asd"
owner : <Admin Detail of created_by id above>
}
]
I have setup only single relationship in my entity : ManyToOne. Not setup relationship in admin table (Id) to OnetoMeny.
How can I get such a data object using typeorm querybuilder. I am using nest js framework for it.
If anyone have some idea how to get data from multiple table. then please help me.
What I tried :
const query = this.Account.createQueryBuilder('account')
.leftJoinAndSelect('account.created_by', 'admin')
.execute()
But It is throwing error like this : create_by is ambiguous.
Please help me how can I get this kind of data?

What is the correct way to UPDATE a document in an embedded list?

I am having some trouble finding a way to update, i.e. modify or delete a certain document in an embedded list. Here is my case:
CREATE CLASS Tag EXTENDS V
CREATE PROPERTY Tag.label STRING
CREATE CLASS Profession
CREATE PROPERTY Profession.jobtitle STRING
CREATE PROPERTY Profession.tags LINKSET Tag
CREATE CLASS UserProfile EXTENDS V
CREATE PROPERTY UserProfile.screenname STRING
CREATE PROPERTY UserProfile.profession EMBEDDEDLIST Profession
So, adding an entry to UserProfile.profession is no problem:
UPDATE UserProfile ADD profession =
{"#type":"d","#class":"Profession","jobtitle":"Actress", "tags" : ["#22:5"]}
WHERE screenname = 'emma'
Given some entry 'emma' for UserProfile and a Tag with id #22:5.
However, when I try to update the Profession-document with jobtitle 'Actress', how exactly should I proceed? I tried the following approach, which worked with but one entry in the list only:
UPDATE UserProfile SET profession =
{"#type":"d","#class":"Profession","jobtitle":"Actress", "tags" : ["#22:7", "#22:9"]}
WHERE profession.jobtitle = 'Actress'
AND screenname = 'emma'
This statement throws no exception and returns 0 as number of affected records.
In general: How do I access a specific entry (using a key of the document itself) in an embedded list or set to update or remove it?
Also: is there an easier way to update the tags linkset in the Profession-document in the embedded list? Or do I always have to get the whole document and write a modified version back?
Thanks!
Ingo
You can use
UPDATE UserProfile set profession = [{"#type":"d","#class":"Profession","jobtitle":"Actress", "tags" : ["#22:7", "#22:9"]}]
WHERE profession.jobtitle contains "Actress" AND screenname = 'emma'
UPDATE
You could use this javascript function
var g=orient.getGraph();
var b=g.command("sql","select from userprofile");
var tag1=g.command("sql","select from #22:7");
var tag2=g.command("sql","select from #22:9");
for(i=0;i<b.length;i++){
var screenname= b[i].getProperty("screenname");
if(screenname=="emma"){
var pro=b[i].getProperty("profession");
for(j=0;j<pro.length;j++){
if(pro[j].field("jobtitle")=="Actress"){
pro[j].field("tags",[tag1[0],tag2[0]]);
}
}
b[i].save();
}
}
try this
UPDATE UserProfile SET profession.jobtitle = 'aaaa'
WHERE profession.jobtitle = 'Actress'
AND screenname = 'emma'

Compare pair of attributes using "IN"

The domain that I'm describing is not the same that I use (with this in mind, there is no need to worry with the fact the the sample class doesn't use Enum for the type, and other things), but describe well my problem. I want to make a query that filter transactions by username and type.
public class Transaction {
private String userName;
private String type;
private BigDecimal value;
...
}
I would like to search all the transactions that match a list of [{'username', 'type'}], where the couple {"username", "type"} is chosen by the user, and the user can choose as many as he wants
For instance: Find all :
"Debit" transactions made by "Rafael"
"Credit" transactions made by "Daniel"
"Debit" transactions made by "Monica"
"Credit" transactions made by "Monica"
I have two possible solutions for my problem, but I don't like any
POSSIBLE SOLUTION 1
I could dynamically add n "OR" clauses to my query, like:
"WHERE (t.userName = 'Rafael' AND t.type = 'Debit')
OR (t.userName = 'Daniel' AND t.type = 'Credit')
... "
POSSIBLE SOLUTION 2
I could concatenate the "username" to the "type" and check if the result is contained by a list of concatenated values of "username" with "type" which was generated dynamically.
CONCAT(t.userName, '-', t.type) IN (list)
for the example, the variable "list" would have the following values:
['Rafael-Debit', 'Daniel-Credit', 'Monica-Debit', 'Monica-Credit']
I'm using JPA, does anyone have a suggestion?

Querying Laravel Relationship

I am trying to get one query work since morning and not able to get it working I have two tables photographers and reviews please have a look at structure and then I will ask the question at the bottom :
Reviews table :
id int(10) unsigned -> primary key
review text
user_id int(10) unsigned foreign key to users table
user_name varchar(64)
photographer_id int(10) unsigned foreign key to photographers table
Photographers table :
id int(10) unsigned -> primary key
name text
brand text
description text
photo text
logo text
featured varchar(255)
Photographers model :
class Photographer extends Model
{
public function reviews()
{
return $this->hasMany('\App\Review');
}
}
Reviews Model :
class Review extends Model
{
public function photographers()
{
return $this->belongsTo('\App\Photographer');
}
}
My logic to query the records
$response = Photographer::with(['reviews' => function($q)
{
$q->selectRaw('max(id) as id, review, user_id, user_name, photographer_id');
}])
->where('featured', '=', 'Yes')
->get();
The question is : I want to fetch all the photographers who have at least one review in the review table, also I want to fetch only one review which is the most latest, I may have more than one review for a photographer but I want only one.
I would add another relationship method to your Photogrpaher class:
public function latestReview()
{
return $this->hasOne('App\Review')->latest();
}
Then you can call:
Photographer::has('latestReview')->with('latestReview')->get();
Notes:
The latest() method on the query builder is a shortcut for orderBy('created_at', 'desc'). You can override the column it uses by passing an argument - ->latest('updated_at')
The with method loads in the latest review.
The has method only queries photographers that have at least one item of the specified relationship
Have a look at Has Queries in Eloquent. If you want to customise the has query further, the whereHas method would be very useful
If you're interested
You can add query methods to the result of a relationship method. The relationship objects have a query builder object that they pass any methods that do not exist on themselves to, so you can use the relationships as a query builder for that relationship.
The advantage of adding query scopes / parameters within a relationship method on an Eloquent ORM model is that they are :
cacheable (see dynamic properties)
eager/lazy-loadable
has-queryable
What you need is best accomplished by a scoped query on your reviews relation.
Add this to your Review model:
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Eloquent\Model;
class Review extends Model {
public function scopeLatest(Builder $query) {
// note: you can use the timestamp date for the last edited review,
// or use "id" instead. Both should work, but have different uses.
return $query->orderBy("updated_at", "desc")->first();
}
}
Then just query as such:
$photographers = Photographer::has("reviews");
foreach ($photographers as $photographer) {
var_dump($photographer->reviews()->latest());
}

How do you clone ( duplicate ) a MongoDB object in a collection of the same db?

I need to duplicate (clone) an object in the collection via dbshell. Having something like this :
> db.users.distinct( 'nickname' )
[
"user1",
"user2",
"user3",
"user4"
]
>
where user1 select a complex object in users collection, how can I duplicate the object then change (rename) user1 field in userX ?
Code
> user = db.users.findOne({'nickname': 'user1'})
> user.nickname = 'userX'
> delete user['_id']
> db.users.insert(user)
Description
You need to find user object and put it into the variable. Than you need to modify the property you want and than you need to insert the whole object as new one. To achieve that you need to delete _id property that the object already has. And than just use insert to create the new one.
Do not delete the _id property; for some reason some values lose their type. For example, integers are converted to doubles.
Use this solution:
var user = db.users.findOne(...)
user._id = new ObjectId()
// set other properties
db.users.insert(user)
The _id field is a required field and we can't delete it like that. What I do is call toJSON() to the returned object and then delete the _id.
var rObject = dbObject.toJSON();
delete rObject._id;
db.insert(rObject);