Any hierarchical Data Support in Doctrine 2? - doctrine

in Doctrine 1, i see that it supports hierarchical data support? is there any in Doctrine 2?
UPDATE 1
ok so i used Nested Set Extension for Doctrine 2. i have some questions
1. inserting a node
// in the docs
$child1 = new Category();
$child1->name = 'Child Category 1';
$child2 = new Category();
$child2->name = 'Child Category 2';
$category->addChild($child1);
$category->addChild($child2);
it seems like i must do something like
$root = $nsm->createRoot($category);
$root->addChild($child1);
$root->addChild($child2);
likewise to add sub children
$child2wrapper = $root->addChild($child2);
$child2wrapper->addChild($newChild);
2. abt the root field and having multiple trees.
say i want multiple trees, i see that the extension does not populate my root field? how shld i populate it?

you can see this links :
http://github.com/guilhermeblanco/Doctrine2-Hierarchical-Structural-Behavior
http://www.devcomments.com/Any-hierarchical-data-support-in-Doctrine-2-at251409.htm

Related

Fetch absolute or relative path using file object in IBM filenet

String mySQLString = "select * from document where documentTitle like '%test%' ";
SearchSQL sql = new SearchSQL(mySQLString);
IndependentObjectSet s = search.fetchObjects(sql, 10, null, true);
Document doc;
PageIterator iterator = s.pageIterator();
iterator.nextPage();
for (Object object : iterator.getCurrentPage()) {
doc = (Document) object;
Properties properties = doc.getProperties();
//I am trying to get an absolute or relative path here for every document.
// for eg: /objectstorename/foldername/filename like this.
}
I have tried searching propeties and class descriptions in document . but can't able to find the path. ?
To do it all in one single query (as you are trying to do in your code) you can create a join with the ReferentialContainmentRelationship table. The property Head of this table points to the document, the property Tail points to the folder the document is filled in and the property ContainmentName is the name the document has in the folder. Use the following code to construct the document path:
SearchSQL searchSQL = new SearchSQL("SELECT R.ContainmentName, R.Tail, D.This FROM Document AS D WITH INCLUDESUBCLASSES INNER JOIN ReferentialContainmentRelationship AS R WITH INCLUDESUBCLASSES ON D.This = R.Head WHERE DocumentTitle like '%test%'");
SearchScope searchScope = new SearchScope(objectStore);
RepositoryRowSet objects = searchScope.fetchRows(searchSQL, null, null, null);
Iterator<RepositoryRow> iterator = objects.iterator();
while (iterator.hasNext()) {
RepositoryRow repositoryRow = iterator.next();
Properties properties = repositoryRow.getProperties();
Folder folder = (Folder) properties.get("Tail").getEngineObjectValue();
String containmentName = properties.get("ContainmentName").getStringValue();
System.out.println(folder.get_PathName() + "/" + containmentName);
}
Paths constructed this way can also be used to fetch the object from the object store. The query code can be optimized by using a property filter as the third argument of the fetchRows() method. Don't know how this behaves if the document is filed in multiple folders.
I suggest you explore the "Creating DynamicReferentialContainmentRelationship Objects" section of FileNet documentation:
https://www.ibm.com/support/knowledgecenter/SSNW2F_5.5.0/com.ibm.p8.ce.dev.ce.doc/containment_procedures.htm#containment_procedures__fldr_creating_a_drcr
A FileNet Ddocument can be assigned to multiple Folders, so you can have several logical "Paths" for a given document.
At end, you should get something like "Folder.get_PathName() + DynamicReferentialContainmentRelationship.get_Name()" to display the full pathname.
As described by samples in FileNet documentation, a relationship object (e.g. DynamicReferentialContainmentRelationship) controls the relation of document/folder:
myRelationshipObject.set_Head(myDocument);
myRelationshipObject.set_Tail(myFolder);
Also, keep in mind that a FileNet Document can be also a "unfiled" document, so there is no actual "pathname" or folder "relationship" to be retrieved.
tl;dr from FileNet Content Engine - Database Table for Physical path
Documents are stored among the directories at the leaf level using a hashing algorithm to evenly distribute files among these leaf directories.

Common part in associations rails, should I use merge?

Update 2
Cama::PostType.first.posts.joins(:custom_field_values)
.where("cama_custom_fields_relationships.custom_field_slug = ? AND
cama_custom_fields_relationships.value LIKE ?","localization",
"%Paris%").merge(Cama::PostType.first.posts.joins(:custom_field_values)
.where("cama_custom_fields_relationships.custom_field_slug = ? AND cama_custom_fields_relationships.value = ?","type-localization", "2"))
Why this merge doesn't work ?
It returns me same result when executed seperately... Merge should work as intersection so common part should be result. I dont get it
Update
I will try to ask in more conceptual way.
I have model B that have slug:text, value:text, belongs_to: Model A
I have model A that have name:string, has_many: Model B
#posts_one = I search for model B where slug="something", value = "city"
#posts_two = I search for model B where slug="mood", value="good"
I have 2 results based on diffrent parameters. Both belongs_to: model A
Now I want to return only the common belongs_to.
so if
#posts_one will return me 20 results with model_a_ids
#posts_two will return me 20 results with model_a_ids
I want to return only common model_a_ids of those 2 queries and right away to find posts. I try to make it in one query but dont know if its possible
Oryginal post
I use Camaleon CMS and I try to create filters based on additional "custom fields". I think to answer this question you dont have to know this cms.
I want to find common part of 2 queries or make it in one query(that would be the best)
I have
#posts = Cama::PostType.first.posts.includes(:custom_field_values)
#param_localization = "Paris"
#param_type_localization = "House"
#posts_one = #posts.merge(CamaleonCms::CustomFieldsRelationship.
where("cama_custom_fields_relationships.custom_field_slug = ? AND
LOWER(cama_custom_fields_relationships.value) LIKE ?", "localization",
"%#{#param_localization}%"))
puts #posts_one.count => 2
#posts_two = #posts.merge(CamaleonCms::CustomFieldsRelationship.where(custom_field_slug:
"type-localization", value: #param_type_localization))
puts #posts_two.count => 2
Question is how can I merge it together or make it one query ? When I made it in one where clause it returns me 0 results since I need to find 2 diffrent custom fields relationships that has diffrent values and slugs but it have relations to posts throught :custom_fields_values, so I have to make 2 queries I guess(like I did). First I find customFieldRelationship with slug = localization and second with slug = type_localization and then I need to find common part
I tried to #result = #posts_one.merge(#posts_two) but I got no result then. I thought it will return me "common part" of association which means 2 results
How can I combine it to find me posts that fullfil both queries ?
Let me know if I explained my problem not well enought.
You'll want to combine it in SQL: (untested)
#posts_combined = #posts.merge(CamaleonCms::CustomFieldsRelationship.
where("(cama_custom_fields_relationships.custom_field_slug = ?
OR cama_custom_fields_relationships.custom_field_slug = 'type-localization')
AND LOWER(cama_custom_fields_relationships.value) LIKE ? ", "localization",
"%#{#param_localization}%"))

datamapper: get object order by relationships fields

I use Codeigniter with datamapper orm and have a problem
this are my models:
mailing -> has many row
row -> has many cell
cell -> has many version
version has one created and one updated field.
I want to get the last 10 mailings order by last version changes created or updated..
I thought to do it like this:
$versions = new Version();
now get last 10 versions order by created or updated
and distinct by mailing_id and now get all mailings to show...
like this: ?
foreach ($version as $v)
{
$v->mailing->get();
}
thx for helping
Yes, you can call ->get() on every related model inside a loop but this would generate a n+1 query scenario and be slow if you are looping over lots of version rows.
You can use the include_related to get full Mailing instances loaded with data when you query Versions in one step (with a join behind a curtain) like this:
$versions = new Version;
$versions->order_by(...)->limit(...); // add your ordering and limiting as before
$versions->include_related('mailing', null, true, true);
// include related mailings, with of their fields and create instances, see
$versions->get();
foreach ($versions as $version) {
// now the $version->mailing is a Mailing instance loaded with the related data
print $version->mailing->id
}

Entity Framework, Table Per Type and Linq - Getting the "Type"

I have an Abstract type called Product, and five "Types" that inherit from Product in a table per type hierarchy fashion as below:
I want to get all of the information for all of the Products, including a smattering of properties from the different objects that inherit from products to project them into a new class for use in an MVC web page. My linq query is below:
//Return the required products
var model = from p in Product.Products
where p.archive == false && ((Prod_ID == 0) || (p.ID == Prod_ID))
select new SearchViewModel
{
ID = p.ID,
lend_name = p.Lender.lend_name,
pDes_rate = p.pDes_rate,
pDes_details = p.pDes_details,
pDes_totTerm = p.pDes_totTerm,
pDes_APR = p.pDes_APR,
pDes_revDesc = p.pDes_revDesc,
pMax_desc = p.pMax_desc,
dDipNeeded = p.dDipNeeded,
dAppNeeded = p.dAppNeeded,
CalcFields = new DAL.SearchCalcFields
{
pDes_type = p.pDes_type,
pDes_rate = p.pDes_rate,
pTFi_fixedRate = p.pTFi_fixedRate
}
}
The problem I have is accessing the p.pTFi_fixedRate, this is not returned with the Products collection of entities as it is in the super type of Fixed. How do I return the "super" type of Products (Fixed) properties using Linq and the Entity Framework. I actually need to return some fields from all the different supertypes (Disc, Track, etc) for use in calculations. Should I return these as separate Linq queries checking the type of "Product" that is returned?
This is a really good question. I've had a look in the Julie Lerman book and scouted around the internet and I can't see an elegant answer.
If it were me I would create a data transfer object will all the properties of the types and then have a separate query for each type and then union them all up. I would insert blanks into the DTO properies where the properties aren't relevant to that type. Then I would hope that the EF engine makes a reasonable stab at creating decent SQL.
Example
var results = (from p in context.Products.OfType<Disc>
select new ProductDTO {basefield1 = p.val1, discField=p.val2, fixedField=""})
.Union(
from p in context.Products.OfType<Fixed>
select new ProductDTO {basefield1 = p.val1, discField="", fixedField=p.val2});
But that can't be the best answer can it. Is there any others?
So Fixed is inherited from Product? If so, you should probably be querying for Fixed instead, and the Product properties will be pulled into it.
If you are just doing calculations and getting some totals or something, you might want to look at using a stored procedure. It will amount to fewer database calls and allow for much faster execution.
Well it depends on your model, but usually you need to do something like:
var model = from p in Product.Products.Include("SomeNavProperty")
.... (rest of query)
Where SomeNavProperty is the entity type that loads pTFi_fixedRate.

Is there a way, using LINQ/EF, to get the top most item in a parent/child hierarchy?

I have a class called Structure:
public class Structure
{
public int StructureId { get; set; }
public Structure Parent { get; set; }
}
As you can see, Structure has a parent Structure. There can be an indefinite number of structures within this hierarchy.
Is there any way, using LINQ (with Entity Framework), to get the top-most structure in this hierarchy?
Currently, I'm having to hit the database quite a few times in order to find the top most parent. The top most parent is a Structure with a null Parent property:
Structure structure = structureRepository.Get(id);
while (structure.Parent != null)
{
structure = structureRepository.Get(structure.Parent.StructureId);
}
// When we're here; `structure` is now the top most parent.
So, is there any elegant way to do this using LINQ/Lambdas? Ideally, starting with the following code:
var structureQuery = from item in context.Structures
where item.StructureId == structureId
select item;
I just want to be able to write something like the following so that I only fire off one database hit:
structureQuery = Magic(structureQuery);
Structure topMostParent = structureQuery.Single();
This is not a direct answer, but the problem you are having is related to the way you are storing your tree. There are a couple ways of simplifying this query by structuring data differently.
One is to use a Nested Set Hierarchy, which can simplify many kinds of queries across trees.
Another is to store a denomralized table of Ancestor/Descendant/Depth tuples. This query then becomes finding the tuple with the current structure as the descendant with the maximum depth.
I think the best I'm going to get is to load the entire hierarchy in one hit from the structure I want the top parent of:
var structureQuery = from item in context.Structures
.Include(x => x.Parent)
where item.StructureId == structureId
select item;
Then just use the code:
while (structure.Parent != null)
{
structure = structure.Parent;
}
I have a similar situation. I didn't manage to solve it directly with LINQ/EF. Instead I solved by creating a database view using recursive common table expressions, as outlined here. I made a user-defined function that cross applies all parents to a child (or vice versa), then a view that makes use of this user-defined function which I imported into my EF object context.
(disclaimer: simplified code, I didn't actually test this)
I have two tables, say MyTable (containing all items) and MyParentChildTable containing the ChildId,ParentId relation
I have then defined the following udf:
CREATE FUNCTION dbo.fn_getsupertree(#childid AS INT)
RETURNS #TREE TABLE
(
ChildId INT NOT NULL
,ParentId INT NULL
,Level INT NOT NULL
)
AS
BEGIN
WITH Parent_Tree(ChildId, ParentId)
AS
(
-- Anchor Member (AM)
SELECT ChildId, ParentId, 0
FROM MyParentChildTable
WHERE ChildId = #childid
UNION all
-- Recursive Member (RM)
SELECT info.ChildId, info.ParentId, tree.[Level]+1
FROM MyParentChildTable AS info
JOIN Parent_Tree AS tree
ON info.ChildId = tree.ParentId
)
INSERT INTO #TREE
SELECT * FROM Parent_Tree;
RETURN
END
and the following view:
CREATE VIEW VwSuperTree AS (
SELECT tree.*
FROM MyTable
CROSS APPLY fn_getsupertree(MyTable.Id) as tree
)
GO
This gives me for each child, all parents with their 'tree level' (direct parent has level 1, parent of parent has level 2, etc.). From that view, it's easy to query the item with the highest level. I just imported the view in my EF context to be able to query it with LINQ.
I like the question and can't think of a linq-y way of doing this. But could you perhaps implement this on your repository class? After all, there should be only one at the top and if the need for it is there, then maybe it deserves a structureRepository.GetRoot() or something.
you can use the linq take construct, for instance
var first3Customers = (
from c in customers
select new {c.CustomerID, c.CustomerName} )
.Take(2);

Resources