In my hyperledger composer app I want to write a named query that returns all persons with two specified hobbies.
The model for "Person" is the following:
participant Person identified by id {
o String id
o String firstName
o String lastName
o String email
--> Hobby[] hobbies optional
}
The model for "Hobby" is the following:
asset Hobby identified by id {
o String id
o String name
}
The named query has the following structure:
query selectPersonsByHobbies {
description: "Select all persons with the two specified hobbies."
statement:
SELECT org.comp.myapp.Person
WHERE //not sure what to put here//
}
I'm not sure what to put after the "WHERE" operator in order to achieve what I want.
Is this correct?:
query selectPersonsByHobbies {
description: "Select all persons with the two specified hobbies."
statement:
SELECT org.comp.myapp.Person
WHERE (hobbies CONTAINS ((name == _$hobby1) AND (name == _$hobby2)))
}
Or is the following correct?:
query selectPersonsByHobbies {
description: "Select all persons with the two specified hobbies."
statement:
SELECT org.comp.myapp.Person
WHERE (hobbies CONTAINS (name == _$hobby1) AND CONTAINS (name == _$hobby2))
}
UPDATE:
Following the answer suggested by Paul O'Mahony, here is how I understand the situation:
Given the following model for "Person":
participant Person identified by id {
o String id
o String firstName
o String lastName
o String email
o Hobby[] hobbies optional
}
and the following model for Hobby:
asset Hobby identified by id {
o String id
o String name
}
the following query would succeed in returning all persons with the two specified hobbies:
query selectPersonsByHobbies {
description: "Select all persons with the two specified hobbies."
statement:
SELECT org.comp.myapp.Person
WHERE ( hobbies CONTAINS [ _$hobby1, _$hobby2] )
}
.... the parameter values sent with the query (and to be inserted for _$hobby1 and _$hobby2, respectively) would have be the Ids of the respective hobbies, correct?
You can't presently, in the Composer Query language, use an aggregate 'AND' in Concepts for CONTAINS currently in the fashion you suggest (OR is fine, but AND you can't) - the name field is compared for each class entry (and it can't be both at the same time with AND). In 0.19.12 onwards of Composer - you could use a getnativeAPI() from a readonly Trxn Processor function to make the equivalent CONTAINS call natively to CouchDB query language.
The AND (as requested above) would work if the field was a String array eg String[] hobbies eg.
query selectPersonsByHobbies {
description: "Select all persons with the two specified hobbies."
statement:
SELECT org.comp.myapp.Person
WHERE ( hobbies CONTAINS [ _$hobby1, _$hobby2] )
}
but your field on Person would have to be Hobby[] hobbies optional (ie not an array of relationships ie relationship IDs as it is presently - ).
Related
I'm new in golang and Gorm
Here is my struct
type SonModel struct {
ID int64
Age int
Name string
FatherID int64
Father FaterModel `gorm:"foreignKey:ID;references:FatherID"`
}
type FaterModel struct {
ID int64
Name string
GrandID int64
Grand GrandModel `gorm:"foreignKey:ID;references:GrandID"`
}
type GrandModel struct {
ID int64
Name string
}
in raw sql what i want is
select son.id,son.name,to_json(father.*) father from son join father on father.id = son.father_id where (son.name like '%name%' or father.name like '%name%') and son.age = 15
i want join and filter with father
in gorm what i'm doing is
db = db.Joins("Father").Preload("Father.Grand")
db = db.Joins("left join father on father.id = son.id left join grand on grand.id = father.grand_id")
db = db.Where("age = ?",15)
db = db.Where("father.name like ? or son.name like ? or grand.name like ?",name)
and i found it left join father and grand twice
first join Father as Father to get father's column
send is my custom left join
how can i Joins("Father") only one time and use its column to filter
Assuming you want to stick with these struct names, there are a couple of things that need to be done.
First, by convention, GORM determines a table name from the struct name. If you want to use different names than that, you need to implement the Tabler interface for each of your models. Something like this:
func (SonModel) Table() string {
return "son"
}
func (FaterModel) Table() string {
return "father"
}
func (GrandModel) Table() string {
return "grand"
}
After this is done, you can write your query like this:
var sons []SonModel
name = fmt.Sprintf("%%%s%%", name) //for example, output in the resulting query should be %John%
err := db.Preload("Father.Grand").
Joins("left join father on father.id = son.father_id").
Joins("left join grand on grand.id = father.grand_id").
Where("sone.age = ?", 15).
Where("son.name like ? or father.name like ? or grand.name like ?", name, name, name).
Find(&sons).Error
I try this code
sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {
return tx.Model(&SonModel{}).Select("son.id, son.name, father.*").Joins("left join father on father.id = son.id").Where("son.name LIKE ?", "%name%").Where("father.name LIKE ?", "%name%").Where("age = ?", 15).Scan(&SonModel{})
})
fmt.Println(sql)
And the result
SELECT son.id, son.name, father.* FROM "son_models" left join father on father.id = son.id WHERE son.name LIKE '%name%' AND father.name LIKE '%name%' AND age = 15
Is this solve your problem?
I am using Postgres with Go Lang & the Echo framework as my base, with that I am using Gorm to build my database queries.
So Here is my Profile Model,
type Profile struct {
gorm.Model
InvoiceCount uint `gorm:"-"`
CompanyName string `gorm:"size:255"`
CompanyNumber string `gorm:"size:10"`
CompanyVatNumber string `gorm:"size:10"`
DateAdded time.Time `gorm:"type:date"`
PrimaryEmail string `gorm:"size:255"`
IsActive bool
Invoice []*Invoice `gorm:"foreignkey:profile_fk" json:",omitempty"`
Address []*Address `gorm:"foreignkey:profile_fk" json:",omitempty"`
}
This is linked into my Invoice model, which I am trying to do a count with on a preload. I added the InvoiceCount uint has a means of adding the count into this model.
So this is what I have tied,
dbCon().
Preload("Invoice", func(db *gorm.DB) *gorm.DB {
return db.Count(&profile)
}).
Find(&profile).
RecordNotFound()
However, I apart from this not working, it returns the following error: (pq: zero-length delimited identifier at or near """").
I am trying to do this with a simple query, but this that wrong? Do I need to just loop around all my profiles and add a count to each? Or drop down to a raw SQL query with a sub select?
Thanks,
I have built this Raw SQL query,
dbConn().
Raw("SELECT p.*, count(i.id) as invoice_count FROM profiles p left join invoices i on i.profile_fk = p.id group by p.id").
Scan(&result)
In my hyperledger composer app I want to write a named query that returns all persons with a certain hobby.
The model for "Person" is the following:
participant Person identified by id {
o String id
o String firstName
o String lastName
o String email
--> Hobby[] hobbies optional
}
The model for "Hobby" is the following:
asset Hobby identified by name {
o String name
}
The named query has the following structure:
query selectPersonsByHobby {
description: "Select all persons with a certain hobby."
statement:
SELECT org.comp.myapp.Person
WHERE //don't know what to put here//
}
I don't know what to put after the "WHERE" operator in order to achieve what I want.
I want something like the following:
query selectPersonsByHobby {
description: "Select all persons with a certain hobby."
statement:
SELECT org.comp.myapp.Person
WHERE (hobbies.contains(_$hobby))
}
Is this even possible ?
The short answer is that this query should work:
query selectConsultantsBySkill {
description: "Select all persons with a certain hobby."
statement:
SELECT org.comp.myapp.Person
WHERE (hobbies CONTAINS _$targetHobby)
}
But note that because your hobbies is an array of Relationships the targetHobby parameter will have to be something like resource:org.acme.Hobby#cycling . In a production scenario you would be 'calling' the query from a UI program so you could pre-pend the relationship syntax.
I guess this is just a test example, but I wonder if Hobby needs to be a relationship? It would be easier if not.
You could alternatively use a concept (and even an enumerated type within the concept!). Here is an example of a modified model and query with a concept:
participant Person identified by id {
o String id
o String firstName
o String lastName
o String email
o Interest[] passTime
}
concept Interest {
o String name
o String description
}
query selectConsultantsBySkill {
description: "Select all persons with a certain hobby."
statement:
SELECT org.comp.myapp.Person
WHERE (passTime CONTAINS (name == _$targetHobby ))
}
Here is my query.
SELECT letter
FROM
Letter AS letter,
(evaluateDisplayName) AS displayName
WHERE
letter.id =: someID
AND displayName =: someDisplayName
// AND etc etc...
The Subquery in this part:
(Do some subquery here) AS displayName
I don't know how to form. But the logic is something like this:
private String evaluateDisplayName(Letter letter) {
def username = letter?.sender?.username
def lastName = letter?.sender?.lastName
def emailAddress = letter?.sender?.emailAddress
return username ?: lastName ?: emailAddress
}
How to turn this into a subquery?
You don't need a subquery, the logic of evaluateDisplayName seems to be the same of the coalesce function: return the first not null value. Try with this:
SELECT letter
FROM
Letter AS letter LEFT JOIN letter.sender AS sender
WHERE
letter.id = :someID
AND COALESCE(sender.username, sender.lastName, sender.emailAddress) = :someDisplayName
// AND etc etc...
i have following query to select the last record in the database
using (Entities ent = new Entities())
{
Loaction last = (from x in ent.Locations select x).Last();
Location add = new Location();
add.id = last.id+1;
//some more stuff
}
the following error is returned when calling the method containing these lines via "Direct event" on ext.net:
LINQ to Entities does not recognize the method 'Prototype.DataAccess.Location Last[Location]
(System.Linq.IQueryable`1[Prototype.DataAccess.Location])' method,
and this method cannot be translated into a store expression.
table structure is following:
int ident IDENTITY NOT NULL,
int id NOT NULL,
varchar(50) name NULL,
//some other varchar fields
Last is not supported by Linq to Entities. Do OrderByDescending (usually by ID or some date column) and select first. Something like:
Location last = (from l in ent.Locations
orderby l.ID descending
select l).First();
Or
Location last = ent.Locations.OrderByDescending(l => l.ID).First();
See MSDN article Supported and Unsupported LINQ Methods (LINQ to Entities) for reference.