I have some doubts related to the queries in orientdb. I have below scenario:
Example :
Performs Uses RunsOn IsConnected
User --> Process --> Application --> Server --> Network
Here, User/Process/Application/Server/Network are Vertex Names
Performs/Uses/RunsOn/IsConnected are Edge Names / Relationship Names
osType/applicationName are Attribute Names for related Vertex
Now, I want all the related combination result as per the input. If input is like osType of Server and applicationName of Application then i want all the details related to this two inputs like user and process and whatever is related to this applicationName and osType.
It is possible in orientdb to fetch out all this details in a single query ??
If you want single columns
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network}
RETURN user.name, process.id, app.name, server.url, server.name, network.name
if you only need the RIDs of the involved elements:
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network}
RETURN user, process, app, server, network
If you also want all the details in line:
SELECT user.* as user_, process.* as process_, app.* as app_, server.* as server_, network.* as network_ FROM (
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network}
RETURN user, process, app, server, network
)
The "as xxx_" will add a prefix to attributes, this is useful to avoid collisions, eg. if you have user.name and server.name, this way you will have "user_name" and "server_name"
If you don't need all the patterns, but you only need single records that are part of the result:
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network}
RETURN $elements
If you have multiple paths connected to the same node, you can use comma separated patterns, joined using aliases, eg.
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network},
{as:server} -IsMountedOn-> {as:storage}
RETURN $elements
If one or more of the (terminal) connections is missing, you can define it as optional, eg. if the storage can be missing:
MATCH
{as:user} -Performs-> {as:process} -Uses->
{class:Application, as:app, where:(applicationName = ?)} -RunsOn->
{class:Server, as:server, where:(osType = ?)} -IsConnected-> {as:network},
{as:server} -IsMountedOn-> {as:storage, optional:true}
RETURN $elements
This works only on terminal nodes, ie. nodes that have only one connection.
Full reference here: http://orientdb.com/docs/2.2.x/SQL-Match.html
Related
I have an existing linq query which gets some data into a view model object. This is working fine.
I want to add a new property for data from child table which will have column values from a child table in a comma separated string format.
Problem: I am not able to concatenate the results using string.join
Simplified version of tables showing only relevant fields
part
id
part number
1
ABC1
2
DEF1
vendor
id
vendorname
1
acme
2
john
vendor part name (vendor specific part number)
partid
vendorid
partname
1
1
GDSE-553-32
1
2
JWWVV-HH-01
simplified version of query
result = (from p in DBContext.Parts.Where(w => w.EquipmentId == eId)
select new PartModel
{
Id = p.Id,
Number = p.PartNumber,
VendorPartNames= String.Join(",", DBContext.VendorPartName.Where(w => w.PartId == p.Id).Select(s => s.PartName))//this line causes exception (shown below)
});
Exception:
LINQ to Entities does not recognize the method 'System.String Join(System.String, System.String[])' method, and this method cannot be translated into a store expression.
Please note: the actual query has some joins and other columns, so please dont suggest solutions that requires joins.
If I change the "VendorPartName" to a List type , I can get the results without any problems.
My only problem is in "How to convert the results for "VendorPartName" property to a comma separated strings?"
eg: based on sample table data provided, it should be
GDSE-553-32, JWWVV-HH-01
Entity Framework does not support String.Join() method.
So, what we can do is to fetch VendorPartNames as a string collection and then we can later separate it with ,.
Note: For this, we would first use an anonymous object and later convert it to PartModel.
So your query would look like this:
var parts = DBContext.Parts
.Where(w => w.EquipmentId == eId)
.Select(p => new {
Id = p.Id,
Number = p.PartNumber,
VendorPartNames = p.VendorPartName.Select(n => n.PartName)
}).ToList();
var result = parts.Select(i => new PartModel {
Id = i.Id,
Number = i.Number,
VendorPartNames = String.Join(",", i.VendorPartNames)
}).ToList();
i created domain in postgres:
create domain arrayofids as numeric[];
Now i want to use the domain in spring data like this:
String fakeQuery = "unnest(CAST (:ids AS arrayofids))";
Query nativeQuery = entityManager.createNativeQuery(fakeQuery);
BigInteger[] arrayOfids = new BigInteger[] {new BigInteger("1"),new BigInteger("2)} //or It can be List. It is not important
nativeQuery.setParameter("ids", arrayOfids);
List resultList = nativeQuery.getResultList();
Of course i get Error:
org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to arrayofIds
Before i used https://dalesbred.org/docs/api/org/dalesbred/datatype/SqlArray.html and it worked fine or did custom types in JDBC myself. Hibernate doesn't allow use my domain easy.
Query like that:
select * from mtTbale where id in :ids
is not interested. I should use the domain with unnest and CAST
Make :ids as a text representation of an array of numbers, i.e. "{1, 2}" and add SELECT to the query.
Try this:
String fakeQuery = "SELECT unnest(CAST (:ids AS arrayofids))";
Query nativeQuery = entityManager.createNativeQuery(fakeQuery);
String arrayOfids = "{" + 1 + ", " + 2 + "}"; // obtain the string as is relevant in your case
nativeQuery.setParameter("ids", arrayOfids);
List resultList = nativeQuery.getResultList();
and the second query should look like this:
select * from mtTbale where id = ANY(CAST(:ids AS arrayofids));
You may also use Postgres shorthand (and more readable) cast syntax.
Instead of CAST(:ids AS arrayofids) use :ids::arrayofids.
This part of the app works, buts it's ugly and not sustainable. Need a more evolved solution.
PROBLEM I AM TRYING TO SOLVE:
This part of the application enables users to access a form to enter purchases they've made and store them in a Postgres DB. I am using Flask SQLAlchemy ORM.
Within my purchase table exists a field store_id, that has a ForeignKey relationship to my store table. I don't want my user to select a store ID # in the form, so I am using a SelectField to enable them to choose the store name instead. However, I can't seem to find a sustainable way to translate the store name back to its associated ID. Right now I am using the ugly IF statements seen below.
What is a better way to map/translate store name to ID which is already housed in the "store" table in my DB?
MY MODEL:
class Purchase(db.Model):
id = db.Column(db.Integer, primary_key=True)
item = db.Column(db.String(80))
quantity = db.Column(db.Integer)
unit_cost = db.Column(db.Integer)
total_cost= db.Column(db.Integer)
date = db.Column(db.DateTime)
store_id = db.Column(db.Integer, db.ForeignKey('store.id'))
MY FORM:
class CreatePurchase(FlaskForm):
item = StringField('Item', validators=[DataRequired()])
quantity = IntegerField('Quantity', validators=[DataRequired()])
unit_cost = IntegerField('Unit Cost', validators=[DataRequired()])
total_cost = IntegerField('Total Cost', validators=[DataRequired()])
store_id = SelectField("Store Selector", choices=[('0','Select Store'),('1','Furgesons'), ('2','Ocean State'), ('3','Chewy'), ('4','Amazon'), ('5', 'Rumford')])
date = DateField('Purchase Date', validators=[DataRequired()])
submit = SubmitField('Enter')
MY ROUTE:
#main.route('/enter_purchases', methods=['GET', 'POST'])
def enter_purchase():
form = CreatePurchase()
x = str(form.store_id) # this is a store name from our form
p = 0
if "Ocean State" in x:
p = 2
elif "Amazon" in x:
p = 4
elif "Furgesons" in x:
p = 1
elif "Chewy" in x:
p = 3
elif "Rumford" in x:
p = 5
if form.validate_on_submit():
purchase = Purchase(item=form.item.data, quantity=form.quantity.data, unit_cost=form.unit_cost.data,
total_cost=form.total_cost.data, date=form.date.data,store_id=p)
db.session.add(purchase)
db.session.commit()
flash('New purchase added successfully')
return redirect(url_for('main.success'))
return render_template('enter_purchases.html', form=form)
You have a store table, with a numeric id (as the PK) and a name attribute:
class Store(db.Model):
store_id = ..
store_name = ..
You populate your form with all of the unique values from the store_name. This needs to be a dynamically generated form, so instead of using a form that is statically created do something like:
def CreatePurchase()
class TempForm(FlaskForm):
item = StringField('Item', validators=[DataRequired()])
quantity = IntegerField('Quantity', validators=[DataRequired()])
unit_cost = IntegerField('Unit Cost', validators=[DataRequired()])
total_cost = IntegerField('Total Cost', validators=[DataRequired()])
date = DateField('Purchase Date', validators=[DataRequired()])
submit = SubmitField('Enter')
choices = ## some SQLalchemy code to get all unique store_names from the table
TempForm.store_id = SelectField("Store Selector", choices=choices)
return TempForm()
Then form.store_id will provide the right id, but display the string name of the store in the form.
The key in this setup is making sure you use the right SQLalchemy code to populate the SelectField dynamically. Basically for each store in the table you can just iterate through something like this:
choices = list()
for store in Store.query.all(): # <- assumes store_id and store_names are unique
choices.append((store.store_id, store.store_name))
i have a collection of financial data stored in mongodb. each company symbol has its data. the question is how to iterate over the collection and change the value of the key which is the symbol company to print out the whole collection and this is my list of companies ['TSLA','TYO','C','LULU','DTV','SHS',' ZNGA'] and this is my cod which return the data of one company:
from pymongo import MongoClient
import csv
host = "localhost"
port = 27017
databaseName = "finance000"
collection_name = "income"
client = MongoClient(host, port)
database = client[databaseName]
collection = database[collection_name]
def finance_data(symbol):
Earnings_BeforeInterestAndTaxes = symbol['statement'[0]EarningsBeforeInterestAndTaxes']['content']
Total_Revenue = symbol['statement'][0]['TotalRevenue']['content']
return Earnings_BeforeInterestAndTaxes,Total_Revenue
i =collection.find({'symbol':'C'})
with open('D:/INCOMEdata.csv', "w") as output:
writer = csv.writer(output, lineterminator='\n')
for key in i :
print finance_data(key)
writer.writerow(finance_data(key))
If I understood you correctly. You want to retrieve the document/data for a given company. The company is denoted by a symbol example 'TYSLA'.
If that is what you need. Here is how you do it (assuming each symbol is unique)
company_data = collection.find({'symbol':'TYSLA'})
The above will return a dictionary. To access an element within the document you just use:
company_data['profit'] #profit is an example of an attribute name. You can use any attribute you like.
Assuming you have multiple companies with the same symbol. If you used the above command. you will get a cursor. to get each company just do a for loop example:
company_data = collection.find({'symbol':'TYSLA'})
Now to loop:
for one in company_date:
print one['profit'] #python 2.7
Now to edit the say for example the profit attribute use $set
collection.update_one({'symbol':'TYSLA'},{'profit':100})
the above will change TYSLA's company profit to 100
Update
Assuming you have a collection with the symbol being any value of ['TSLA','TYO','C','LULU','DTV','SHS',' ZNGA']. to get the data for any of the symbols you use (assuming symbol contains any of the names (only one name)):
you use the $or as:
collection.find({"$or":[ {'symbol':'TSLA},{'symbol':'TYO},... ]},{}) #the ... are the rest of the names you need
The above returns the whole data for a given symbol. To return the specifics Total_Revenue and Earnings_BeforeInterestAndTaxes you use the following:
collection.find({"$or":[ {'symbol':'TSLA},{'symbol':'TYO},... ]},{'Total_Revenue ':1,'Earnings_BeforeInterestAndTaxes ':1, _id:0 }) #if you remove _id it will always be returned
I hope that helps.
I have a table patient_details(patient_id, first_name, last_name, address,date_of_birth, gender, contact_number,occupation). I have generated an entity class and a PersistenceUnit. I can only find an object using its ID:
PatientDetails pd = em.find(PatientDetails.class,patient_id);
I want to know how to find an object by using other column name(s) instead of just the primary key.
Have a look on JPQL or JPA Critera.
https://docs.oracle.com/html/E24396_01/ejb3_langref.html
http://docs.oracle.com/javaee/6/tutorial/doc/gjitv.html
Execute Querys:
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#createQuery%28javax.persistence.criteria.CriteriaQuery%29
For example:
if
class PatientDetails
String first_name;
#Column(",date_of_birth")
Date birth;
...
}
then
String sql = "SELECT p FROM PatientDetails p where p.first_name = :fname and p.birth > :generation";
Date generation = new Date(int 1980, 0, 1);
TypedQuery<PatientDetails> query = EM.createQuery(sql);
query.setParameter("fname","John");
query.setParameter("generation",generation);
return query.getResultList
returns patients called John and born after 1980.
But you should read the links recommended by #pL4Gu33