How to extend 'join' query in elastic-search? - elasticsearch

As so far, elasticsearch is not support join query.
Offical documents give several suggestions to do join query, which may be a little complicated and not easy to use.
https://www.elastic.co/guide/en/elasticsearch/reference/current/joining-queries.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/relations.html
opensearch provide SQL search plugin to support two indices join query.
https://opensearch.org/docs/latest/search-plugins/sql/complex/
We can write such sql query in opensearch:
SELECT
a.account_number, a.firstname, a.lastname,
e.id, e.name
FROM accounts a
JOIN employees_nested e
ON a.account_number = e.id
How to extend this ability to elastic search so that we can write queries to join two indices?
Thank you.

Related

Hibernate + Oracle Group By Results in ORA-00979: not a GROUP BY expression error

I have the following Hibernate HQL query:
select t from Term t join ApprovedCourse ap on t.id = ap.term.id group by t order by t desc
It's failing with the
ORA-00979: not a GROUP BY expression
error because Oracle insists that all select values be in the group by. Hibernate, of course, is hiding the various fields of the Term object from us, letting us deal with it as a Term and not Term.id. (This query works on Postgres, by the way. Postgres is more liberal about its group by requirements.)
Hibernate is producing the following SQL:
select term0_.id as id1_12_, term0_.semester_id as semester_id2_12_, term0_.year_id as year_id3_12_
from term term0_
inner join approved_course approvedco1_
on (term0_.id=approvedco1_.term_id)
group by term0_.id
order by term0_.id desc
I've tried just removing the select t from the start of the query, but then Hibernate assumes that I'm selecting both the Term and ApprovedCourse objects, and that makes things worse.
So how do I make this work in a Hibernate way?
I found that I could get what I want by replacing the group by clause with a distinct in the select clause. Here's the resulting query:
select distinct(t) from Term t join ApprovedCourse ap on t.id = ap.term.id order by t desc

JOIN 4 tables in one (Oracle R11)

I need to create a query that shows the "Legal Entity", "Application Name", "Close Date" and "Period" I'm working with Oracle R11, Right now I've found the query for
"Legal Entity"
SELECT name
FROM hr_organization_information HOI
INNER JOIN hr_all_organization_units HAOU
ON HOI.ORGANIZATION_ID = Haou.Organization_Id
WHERE HOI.org_information_context LIKE 'Legal Entity Accounting'
ORDER BY NAME ASC;
and for "Application Name, Close Date, Period"
SELECT A.APPLICATION_ID,
B.APPLICATION_NAME,
TO_CHAR(A.END_DATE,'HH24:MI DD-MON-YYYYI'),
A.PERIOD_NUM
FROM GL_PERIOD_STATUSES A
INNER JOIN FND_APPLICATION_TL B ON A.APPLICATION_ID = B.APPLICATION_ID
WHERE A.Application_Id=101
AND LANGUAGE='US'
OR A.APPLICATION_ID=200
AND LANGUAGE='US'
OR A.APPLICATION_ID=222
AND LANGUAGE='US';
Separately but I haven't found the way to join them in one query, can you help me with that?
Antonio, I think Brian has given you sound advice. Posting to an EBS forum (or whatever application this is) might also be worthwhile if his advice has not lead you to the answer. I will offer that sometimes the way to join table_A and table_B is through table_C. That is, if you do not find any directly related data in the queries of one se to one of the tables in the other set then look at the FK defined on and pointing to these tables to see if you can find a table not currently part of either query that relates the sets. You figure out how to join each of your current queries to it and that is how you join the two queries together.
Thank you all!
The advices that all of you gave to me were useful, I've found the table HR_LEGAL_ENTITIES (Table C) that have two columns that allow me to join Table A with Table B, the final query was:
SELECT HAOU.NAME,
FAT.APPLICATION_NAME,
TO_CHAR(GPS.END_DATE,'HH24:MI DD-MON-YYYY'),
GPS.PERIOD_NUM
FROM HR_ALL_ORGANIZATION_UNITS HAOU
INNER JOIN HR_LEGAL_ENTITIES HLE
ON HLE.ORGANIZATION_ID = HAOU.ORGANIZATION_ID
INNER JOIN GL_PERIOD_STATUSES GPS
ON HLE.SET_OF_BOOKS_ID = GPS.SET_OF_BOOKS_ID
INNER JOIN FND_APPLICATION_TL FAT
ON GPS.APPLICATION_ID = FAT.APPLICATION_ID
WHERE GPS.Application_Id IN (101,200,222) AND LANGUAGE='US'
ORDER BY NAME ASC;
Regards!

Dynamics CRM 2011 - Filtering LINQ query with outer joins

I have a requirement to query for records in CRM that don't have a related entity of a certain type. Normally, I would do this with an Left Outer Join, then filter for all the rows that have NULLs in the right-hand side.
For example:
var query = from c in orgContext.CreateQuery<Contact>()
join aj in orgContext.CreateQuery<Account>()
on c.ContactId equals aj.PrimaryContactId.Id
into wonk
from a in wonk.DefaultIfEmpty()
where a.Name == null
select new Contact
{
FirstName = c.FirstName,
LastName = c.LastName,
};
This should return me any Contats that are not the Primary Contact of an account. However, this query ends up returning all contacts...! When you look at the SQL that gets generated in SQL Profiler it comes out like this:
SELECT cnt.FirstName, cnt.LastName
FROM Contact as cnt
LEFT OUTER JOIN Account AS acct
ON cnt.ContactId = acct.PrimaryContactId AND acct.Name is NULL
So, I get the Left Join OK, but the filter is on the Join clause, and not in a WHERE clause.and not as it should, like this:
SELECT cnt.FirstName, cnt.LastName
FROM Contact as cnt
LEFT OUTER JOIN Account AS acct
ON cnt.ContactId = acct.PrimaryContactId
WHERE acct.Name is NULL
Clearly, the results from this query are very different! Is there a way to get the query on CRM to generate the correct SQL?
Is this a limitation of the underlying FetchXML request?
Unfortunately, this is a limitation of CRM's LINQ and FetchXML implementations. This page from the SDK states outer joins are not supported:
http://technet.microsoft.com/en-us/library/gg328328.aspx
And while I can't find an official document, there are a lot of results out there for people mentioning FetchXML does not support left outer joins, for example:
http://gtcrm.wordpress.com/2011/03/24/fetch-xml-reports-for-crm-2011-online/
Try this:
var query = from c in orgContext.CreateQuery<Contact>()
where orgContext.CreateQuery<Account>().All(aj => c.ContactId != aj.PrimaryContactId.Id)
select new Contact
{
FirstName = c.FirstName,
LastName = c.LastName,
};
If you don't need to update the entity (e.g. to process all the corresponding validation rules and workflow steps), you can write less-ugly and more efficient queries by hitting the SQL Server directly.
Per CRM's pattern, the views take care of most of the common joins for you. For instance, the dbo.ContactBase and dbo.ContactExtensionBase tables are already joined for you in the view dbo.Contact. The AccountName is already there (called AccountIdName for some bizarre reason, but at least it's there).

How can i perform this query in NHibernate for getting child count

select name,
(select count(*) from products where products.category_Id=categories.Id) as productCount
from categories
session.CreateCriteria<Category>()
but whats next?
i don't even know how to search it in Google?
think of your query like
SELECT categories.Id, count(categories.Id)
FROM categories inner join products on products.category_Id=categories.Id
group by categories.Id
I think they will produce the same result.
search google for
nhibernate criteria join
and
CreateAlias

Linq to entities Left Join

I want to achieve the following in Linq to Entities:
Get all Enquires that have no Application or the Application has a status != 4 (Completed)
select e.*
from Enquiry enq
left outer join Application app
on enq.enquiryid = app.enquiryid
where app.Status <> 4 or app.enquiryid is null
Has anyone done this before without using DefaultIfEmpty(), which is not supported by Linq to Entities?
I'm trying to add a filter to an IQueryable query like this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where e.Applications.DefaultIfEmpty()
.Where(app=>app.Status != 4).Count() >= 1
select e);
Thanks
Mark
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Do this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where (!e.Applications.Any())
|| e.Applications.Any(app => app.Status != 4)
select e);
I don't find LINQ's handling of the problem of what would be an "outer join" in SQL "goofy" at all. The key to understanding it is to think in terms of an object graph with nullable properties rather than a tabular result set.
Any() maps to EXISTS in SQL, so it's far more efficient than Count() in some cases.
Thanks guys for your help. I went for this option in the end but your solutions have helped broaden my knowledge.
IQueryable<Enquiry> query = Context.EnquirySet;
query = query.Except(from e in query
from a in e.Applications
where a.Status == 4
select e);
Because of Linq's goofy (read non-standard) way of handling outers, you have to use DefaultIfEmpty().
What you'll do is run your Linq-To-Entities query into two IEnumerables, then LEFT Join them using DefaultIfEmpty(). It may look something like:
IQueryable enq = Enquiry.Select();
IQueryable app = Application.Select();
var x = from e in enq
join a in app on e.enquiryid equals a.enquiryid
into ae
where e.Status != 4
from appEnq in ae.DefaultIfEmpty()
select e.*;
Just because you can't do it with Linq-To-Entities doesn't mean you can't do it with raw Linq.
(Note: before anyone downvotes me ... yes, I know there are more elegant ways to do this. I'm just trying to make it understandable. It's the concept that's important, right?)
Another thing to consider, if you directly reference any properties in your where clause from a left-joined group (using the into syntax) without checking for null, Entity Framework will still convert your LEFT JOIN into an INNER JOIN.
To avoid this, filter on the "from x in leftJoinedExtent" part of your query like so:
var y = from parent in thing
join child in subthing on parent.ID equals child.ParentID into childTemp
from childLJ in childTemp.Where(c => c.Visible == true).DefaultIfEmpty()
where parent.ID == 123
select new {
ParentID = parent.ID,
ChildID = childLJ.ID
};
ChildID in the anonymous type will be a nullable type and the query this generates will be a LEFT JOIN.

Resources