first off all I´m new to Jena. I´ve created an ontology and i´ve 4 classes, procedure, buyer, supplier and Zip Code.And i´ve the following properties:
Procedure hasBuyer Buyers
Procedure hasSupplier Supplier
Supplier hasZipCode Zip Code
Buyer hasZipCode Zip Code
What i want to know it´s the best approach in Jena to return all domains that contain a string "3333".
For example:
Procedure 1 have buyer 1 with zip code 333, supplier 1 with zip code 333 and supplier2 with zip code 334.
Procedure 2 have buyer 2 with zip code 331, supplier 2 with zip code 334 and supplier2 with zip code 335.
Procedure 3 have buyer 3 with zip code 333, supplier 1 with zip code 333 and supplier3 with zip code 335.
The results must be:
Procedures - Procedure1 and Procedure3
Buyer - Buyer1 and Buyer 3
Supplier - supplier1
NG
First of all, you can't use "supplier 2 with zip code 334", and then "supplier 2 with zip code 335", because it's the same individual, and you'll see "supplier 2 with zip code 334 and zip code 334" in application both times.
There is some variants of realisation.
With plain Jena API:
Model model; // your model
Resource supplierClass = model.getResource(YOUR_NS + "Supplier");
Resource buyerClass = model.getResource(YOUR_NS + "Buyer");
Resource procClass = model.getResource(YOUR_NS + "Procedure");
Property zipCodeProp = model.getProperty(YOUR_NS + "zipCode");
Property hasBuyerProp = model.getProperty(YOUR_NS + "hasBuyer");
Property hasSupplierProp = model.getProperty(YOUR_NS + "hasSupplier");
StmtIterator iter =
model.listStatements(new SimpleSelector(null, zipCodeProp, "333"));
while (iter.hasNext()) {
Resource subject = iter.next().getSubject();
if (!subject.hasProperty(RDF.type))
continue;
Resource subjectClass = subject.getPropertyResourceValue(RDF.type);
SimpleSelector sel;
if (subjectClass.equals(supplierClass))
sel = new SimpleSelector(null, hasSupplierProp, subject);
else if (subjectClass.equals(buyerClass))
sel = new SimpleSelector(null, hasBuyerProp, subject);
else
continue;
StmtIterator innerIter = model.listStatements(sel);
while (innerIter.hasNext()) {
Resource proc = innerIter.next().getSubject();
if (!proc.hasProperty(RDF.type) ||
!proc.getPropertyResourceValue(RDF.type).equals(procClass))
continue;
// now you can retrieve linked entities from this procedure
}
}
And SPARQL query:
PREFIX yourns: <YOUR_NS>
SELECT DISTINCT ?proc
{
?proc a yourns:Procedure;
yourns:hasBuyer ?buyer;
yourns:hasSupplier ?supplier.
?supplier zipCode ?supplierZip.
?buyer zipCode ?buyerZip.
FILTER (?supplierZip = '333' || ?buyerZip = '333')
}
with further use of ARQ:
Query query = QueryFactory.create(queryString);
QueryExecution qe = QueryExecutionFactory.create(query, model);
ResultSet results = qe.execSelect();
while (results.hasNext()) {
QuerySolution qs = results.next();
Resource proc = qs.getResource("proc");
// now again you can retrieve linked entities
}
Related
I understand that stored procedures run in the scope of a single partition key.
It is also possible to do operations that change data, not just read it.
ID must be string, so I must roll my own autoincrementer for a separate property to use in documents.
I am trying to make a simple autoincrement number generator that runs in a single stored procedure.
I am partitioning data mimicking a file tree, using forward slashes to separate+concatenate significant bits that make my partition names. Like so:
/sometype/foo/bar/
/sometype/ids/
The first item is always the document type, and every document type will have a 'ids' sub-partition.
Instead of holding documents, the /sometype/ids/ partition will hold and reserve all numerical ids that have been created for this document type, for autoincrement purposes.
this satisfies uniqueness within a partition, stored procedure execution scope, and unique document count within a document type, which is good for my purposes.
I got stumped in a stored procedure where I want to get a specified id, or create it if it does not exist.
I can query my partition with the stored procedure, but the upsert throws an error, using the same partition key.
I designed my database with "pkey" as the name of the property that will holds my partition keys.
Here is the code:
//this stored procedure is always called from a partition of type /<sometype>/ids/ , where <sometype> os one of my document types.
//the /sometype/ids/ is a partition to reserve unique numerical ids, as Cosmos DB does not have a numerical increment out of the box, I am creating a facility for that.
//the actual documents of /sometype/ will be subpartitioned as well for performance.
function getId(opkey, n, id) {
// gets the requested number if available, or next one.
//opkey: string - a partition key of cosmos db of the object that is going to consume the generated ID, if known. must start with /<sometype>/ which is the same that is being used to call this SP
//n: integer - a numerical number for the autoincrement
//id = '' : string - a uuid of the document that is using this id, if known
if (opkey === undefined) throw new Error('opkey cannot be null. must be a string. must be a valid partition key on Cosmos DB.');
n = (n === undefined || n === null)?0:n;
id = (id === undefined || id === null)?'':id;
var collection = getContext().getCollection();
//make opkey parameter into an array
var split_pkey = opkey.split('/');
//recreate the pkey /<sometype>/ids/ because I can't find a reference to this string inside the context.
var idpkey = '/'+split_pkey[1]+'/ids/';
//first query as SQL
//get highest numerical value.
var q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' ORDER BY c.n desc';
//helper function to create uuids. can I ditch it?
function CreateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Query documents and take 1st item.
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (firstError, feed, options) {
if (firstError) throw "firstError:"+firstError;
//console.log(collection.options.);
console.log(idpkey+', '+n+', '+id+"-");
var maxn = 0;
// take 1st element from feed
if (!feed || !feed.length) {
//var response = getContext().getResponse();
//response.setBody(null);
}
else {
maxn = feed[0].n;
//var response = getContext().getResponse();
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
console.log(maxn);
//query for existing numerical value
q = 'SELECT TOP 1 * FROM c \
WHERE c.pkey = \''+idpkey+'\' \
AND \
c.number = '+n+' \
OR \
c.id = \''+id+'\'';
var isAccepted2 = collection.queryDocuments(
collection.getSelfLink(),
q
,
function (secondFetchError, feed2, options2) {
if (secondFetchError) throw "second error:"+secondFetchError;
//if no numerical value found, create a new (autoincrement)
if (!feed || !feed.length) {
console.log("|"+idpkey);
var uuid = CreateUUID();
var newid = {
id:uuid,
pkey:idpkey,
doc_pkey:opkey,
n:maxn+1
};
//here I used the javascript query api
//it throws an error claiming the primary key is different and I don't know why, I am using idpkey all the time
var isAccepted3 = collection.upsertDocument(
collection.getSelfLink(),
newid
,
function (upsertError,feed3,options3){
if (upsertError) throw "upsert error:"+upsertError;
//if (upsertError) console.log("upsert error:|"+idpkey+"|");
//var response = getContext().getResponse();
//response.setBody(feed[0]);
});
if (!isAccepted3) throw new Error('The third query was not accepted by the server.');
console.log(" - "+uuid);
}
else {
//if id found, return it
//maxn = feed[0].n;
var response = getContext().getResponse();
response.setBody(feed[0]);
//var body = { original: '', document: '', feed: feed[0] };
//response.setBody(JSON.stringify(body));
}
});
if (!isAccepted2) throw new Error('The second query was not accepted by the server.');
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
The error message is :
"Requests originating from scripts cannot reference partition keys other than the one for which client request was submitted."
I don't understand why it thinks it is in error, as I am using the variable idpkey in all queries to hold the correct pkey.
Talk about brain fart!
I was violating my own rules because I was misspelling the partition name in the request, making the first part of the partition key /sometype/ different from the parameter sent, causing a mismatch between the execution scope's partition key and the idpkey variable, resulting in the error.
I did raw SQL query below to select only certain fields from a table.
{
List<CustEmpVM> CustomerVMlist = new List<CustEmpVM>();
var cid = db.Customers.SqlQuery("select SchedDate from Customer where CustID = '#id'").ToList<Customer>();
}
But i keep getting the error of:
System.Data.Entity.Core.EntityCommandExecutionException occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The data reader is incompatible with the specified ALFHomeMovers.Customer. A member of the type, CustID, does not have a corresponding column in the data reader with the same name.
The exception message is pretty straightforward: the query expected to return full entity of Customer table but only SchedDate column returned, hence EF cannot done mapping other omitted columns including CustID.
Assuming Customers is a DbSet<Customer>, try return all fields from Customer instead:
// don't forget to include SqlParameter
var cid = db.Customers.SqlQuery("SELECT * FROM Customer WHERE CustID = #id",
new SqlParameter("id", "[customer_id]")).ToList();
If you want just returning SchedDate column, materialize query results and use Select afterwards:
var cid = db.Customers.SqlQuery("SELECT * FROM Customer WHERE CustID = #id",
new SqlParameter("id", "[customer_id]"))
.AsEnumerable().Select(x => x.SchedDate).ToList();
NB: I think you can construct LINQ based from the SELECT query above:
var cid = (from c in db.Customers
where c.CustID == "[customer_id]"
select c.SchedDate).ToList();
Similar issue:
The data reader is incompatible with the specified Entity Framework
Use below query instead of raw query:
{
List<CustEmpVM> CustomerVMlist = new List<CustEmpVM>();
var cid = db.Customers.Where(w=>w.Id == YOURCUSTOMERID).Select(s=>new Customer{SchedDate = s.SchedDate }).ToList();
}
It will give compile time error rather than run time error.
I have two files,
one is titles.csv and has a movie ID and title with this format:
999: Title
734: Another_title
the other is a list of user IDs who link to the movie
categoryID: user1_id, ....
222: 120
227: 414 551
249: 555
Of different sizes (minimum is one user per genre category)
The goal is to first parse the strings so that they are each split into two (for both files), everything before the ':' and everything after.
I have tried doing this
movies = LOAD .... USING PigStorage('\n') AS (line: chararray)
users = LOAD .... USING PigStorage('\n') AS (line: chararray)
-- parse 'users'/outlinks, make a list and count fields
tokenized = FOREACH users GENERATE FLATTEN(TOKENIZE(line, ':')) AS parameter;
filtered = FILTER tokenized BY INDEXOF(parameter, ' ') != -1;
result = FOREACH filtered GENERATE SUBSTRING(parameter, 2, (int)SIZE(parameter)) AS number;
But this is where I got stuck/confused. Thoughts?
I'm also supposed to output the top 10 entries who have the most user IDs in the second part of the string.
try like this
movies = LOAD 'file1' AS titleLine;
A = FOREACH movies GENERATE FLATTEN(REGEX_EXTRACT_ALL(titleLine,'^(.*):\\s+(.*)$')) AS (movieId:chararray,title:chararray);
users = LOAD 'file2' AS userLine;
B = FOREACH users GENERATE FLATTEN(REGEX_EXTRACT_ALL(userLine,'^(.*):\\s+(.*)$')) AS (categoryId:chararray,userId:chararray);
Output1:
(999,Title)
(734,Another_title)
Output2:
(222,120)
(227,414 551)
(249,555 )
Say I have a stored procedure that returns dataSet from 2 different tables. Example:
SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers LEFT JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName
Is there any way to get a strongly typed list as a result from this stored procedure ? Something like this:
StoredProcedure sp = myDevDB.GetCustomerSales();
List<MyCustomType> resultSet = sp.ExecuteTypedList<MyCustomType>();
How and where do I define the MyCustomType class ? How do I map its properties to the actual table columns ?
Thanks,
Zohrab.
I just created a asp.net web page that does this. Try this:
DataSet ds = new DataSet();
SqlDataAdapter adtp = new SqlDataAdapter(command);
adtp.Fill(ds);
StringBuilder b = new StringBuilder();
b.AppendLine("class " + this.txtSP.Text + "_QueryResult");
b.AppendLine("{");
foreach ( DataColumn c in ds.Tables[0].Columns )
{
b.AppendLine(string.Format("property {0} {1} {{ get; set; }}", c.DataType, c.ColumnName));
}
b.AppendLine("}" + Environment.NewLine);
this.txtResult.Text = b.ToString();
}
catch { }
I have a rather simple scenario where I have two tables in which I want to add data. They are managed with primary key/foreign key. I want to add new data into TABLE A and then retrieve the Id and insert into TABLE B.
I can certainly do it with a stored procedure, but I'm looking at trying to do it using Linq.
What is the best approach ?
I can certainly get the ID and do two separate inserts but that doesn't certainly seem to be a very good way of doing things.
db.Table.InsertOnSubmit(dbObject);
db.SubmitChanges();
Int32 id = dbOject.Id;
//Rest of the code
Any way to elegantly do this?
Do you have the relationship defined between the 2 tables in the object relational designed? If so, you can have linq take care of assigning the ID property of the second table automatically.
Example...
Table A – Order
OrderId
OrderDate
Table B – Order Item
OrderItemId
OrderId
ItemId
Code (Using LINQ-to-SQL):
Order order = new Order();
Order.OrderDate = DateTime.Now();
dataContext.InsertOnSubmit(order);
OrderItem item1 = new OrderItem();
Item1.ItemId = 123;
//Note: We set the Order property, which is an Order object
// We do not set the OrderId property
// LINQ will know to use the Id that is assigned from the order above
Item1.Order = order;
dataContext.InsertOnSubmit(item1);
dataContext.SubmitChanges();
hi i insert data into three table using this code
Product_Table AddProducttbl = new Product_Table();
Product_Company Companytbl = new Product_Company();
Product_Category Categorytbl = new Product_Category();
// genrate product id's
long Productid = (from p in Accountdc.Product_Tables
select p.Product_ID ).FirstOrDefault();
if (Productid == 0)
Productid++;
else
Productid = (from lng in Accountdc.Product_Tables
select lng.Product_ID ).Max() + 1;
try
{
AddProducttbl.Product_ID = Productid;
AddProducttbl.Product_Name = Request.Form["ProductName"];
AddProducttbl.Reorder_Label = Request.Form["ReorderLevel"];
AddProducttbl.Unit = Convert.ToDecimal(Request.Form["Unit"]);
AddProducttbl.Selling_Price = Convert.ToDecimal(Request.Form["Selling_Price"]);
AddProducttbl.MRP = Convert.ToDecimal(Request.Form["MRP"]);
// Accountdc.Product_Tables.InsertOnSubmit(AddProducttbl );
// genrate category id's
long Companyid = (from c in Accountdc.Product_Companies
select c.Product_Company_ID).FirstOrDefault();
if (Companyid == 0)
Companyid++;
else
Companyid = (from Ct in Accountdc.Product_Companies
select Ct.Product_Company_ID).Max() + 1;
Companytbl.Product_Company_ID = Companyid;
Companytbl.Product_Company_Name = Request.Form["Company"];
AddProducttbl.Product_Company = Companytbl;
//Genrate Category id's
long Categoryid = (from ct in Accountdc.Product_Categories
select ct.Product_Category_ID).FirstOrDefault();
if (Categoryid == 0)
Categoryid++;
else
Categoryid = (from Ct in Accountdc.Product_Categories
select Ct.Product_Category_ID).Max() + 1;
Categorytbl.Product_Category_ID = Categoryid;
Categorytbl.Product_Category_Name = Request.Form["Category"];
AddProducttbl.Product_Category = Categorytbl;
Accountdc.Product_Tables.InsertOnSubmit(AddProducttbl);
Accountdc.SubmitChanges();
}
catch
{
ViewData["submit Error"] = "No Product Submit";
}