SOLR - How to handle AND clause between 2 multivalue fields - solr

How would we use AND clause in the SOLR query between 2 fields those are multiple value fields?
For example; following is the picture of database table
JobseekerID CompanyID Email Sent On
=========== =========== ==============
123 ABC 22-Jul-2011
123 XYZ 01-Jul-2011
Now in Sql, if i query
Where CompanyID = "ABC" AND EmailSentOn > 14-Jul-2011 (It will return TRUE)
Where CompanyID = "XYZ" AND EmailSentOn > 14-Jul-2011 (It will return FALSE)
How would we handle it in SOLR? Following is the picture of my SOLR Collection, how i am storing the data
{int name="jobseekerid"}123{/int}
.....................
.....................
.....................
{arr name="CompanyID"}
{str}ABC{/str}
{str}XYZ{/str}
{/arr}
{arr name="EmailSentOn"}
{str}2011-07-22T17:44:00Z{/str}
{str}2011-07-01T05:10:00Z{/str}
{/arr}
How can i query in the SOLR Now for Jobseeker 123. Because for SOLR there is not any relation between CompanyID and EmailSentON. It takes them two separate entities.
When we will query Company ID is "ABC" and EmailSentOn >= 14-July-2011 it will return TRUE and when we will say CompanyID is "XYZ" and EmailSentOn >= 14-July-2011 it will again return TRUE because SOLR will see, does company ID "XYZ" exist and any date in the 'email sent on' is greater than 14-July then it will return true.
But we need it to check if the CompanyID "XYZ" then the company XYZ date is greater than 14-july or not. Which is not, because XYZ sent email date is "01-Jul". So it should return false for that.
I hope you get my point. Can anyone please guide me how would we handle this in SOLR?

The problem here is with the definition of the schema - you don't actually have multiValued data! Instead, you should just have two separate indexed documents with single values for CompanyId and EmailSentOn. Then when you search by date you get back just the contents of one document or another and don't have the results jumbled as you do now.

Related

Force uniqueness in JSONB array

Let's say I have a table students with a column type jsonb where I store a list with students' additional emails. A student row looks like this
student_id
name
emails
1
John Doe
[j.doe#email.com]
I'm using the following query to update the emails column:
UPDATE students SET emails = emails || '["j.doe#email.com"]'::jsonb
WHERE student_id=1
AND NOT emails #> '["j.doe#email.com"]'::jsonb;
Once the column emails is filled, if I reuse query above with the parameter ["j.doe#email.com", "john#email.com"], the column emails would be update with repeated value:
student_id
name
emails
1
Student 1
[j.doe#email.com, j.doe#email.com, john#email.com]
Is there a way to make sure that in the column emails I'll always have a jsonb list with only unique values ?
Use this handy function which removes duplicates from a jsonb array:
create or replace function jsonb_unique_array(jsonb)
returns jsonb language sql immutable as $$
select jsonb_agg(distinct value)
from jsonb_array_elements($1)
$$;
Your update statement may look like this:
update students
set emails = jsonb_unique_array(emails || '["j.doe#email.com", "john#email.com"]'::jsonb)
where student_id=1
and not emails #> '["j.doe#email.com", "john#email.com"]'::jsonb
Test it in db<>fiddle.

Salesforce(apex) Query select with Where toLowerCase

I using Salesforce (apex), I need to Query with a WHERE statement with toLowerCase ,i.e. I have a list (MyNames_list) with LowerCase values but the table values are not lowerCase.
In my Query when I check the Name in MyNames_list it will make toLowerCase value and then check it in the MyNames_list.
Something like this:
Name | LastName
BOBY | Testovich1
DANY | Testovich2
Ron | Testovich3
and in my list:
MyNames_list :boby,dany,ron
That still will return me all rows, because WHERE statement will check it with LowerCase.
//only example (not working code)
for(Users user:[SELECT Name,LastName FROM Users
WHERE ( Name.toLowerCase() IN : MyNames_list) ] )
{
//code....
}
Is there a way to do this in Salesforce (apex) Query ?
Salesforce is only case-sensitive for fields that are explicitly case-sensitive (ie an external id that has been marked as case-sensitive)
The field you are querying, Name is not case-sensitive - hence, you don't need to apply toLowerCase(). You will get all matching fields anyway.
So your query could be:
for(User u:[SELECT Name,LastName FROM User WHERE Name IN :MyNames_list)]){
//code....
}

getting join results in Solr

I have indexed two document types in solr viz analysis and issue_summery
The fields for analysis:
doc_id
doc_type
title
description
The fields for issue_summery:
doc_id
doc_type
issue_parent_id (this is fk from analysis [doc_id])
summery
issue_id (this comes from another table)
analysis has one to many relationship with issue_summery.
I am using a join query as follows:
q={!join+from=issue_parent_id+to=doc_id}doc_type:issue_summery
and it works as I expected. Now when I search with specific issue_id
&q={!join+from=issue_parent_id+to=doc_id}doc_type:issue_summery+AND+issue_id:(+issue_103)
This query returns results with issue id = 103
But when I query by multiple issue ids like
&q={!join+from=issue_parent_id+to=doc_id}doc_type:issue_summery+AND+nature_of_the_issues_summery:(issue_322+issue_82)&rows=20&start=0&json.nl=map
It returns results where issue_id = issue_322 OR issue_id=issue_82
I am expecting ANDing here ie. I need to get those analysis docs which contains issue_id = issue_322 AND issue_82 rather than: issue_id = issue_322 OR issue_82
Thanks in advance.

Searching in two columns

I have a solr schema consisting of name and idnumber.
name column stores name of a person
idnumber stores numbers of passport/driving license ets.
My search condition is like
Get all results when the name of person is 'ABC' or idnumber is '123'
I used the query
(name:'MAHMUD ABID HAMID BID HAMID' OR idnumber:123)
AND (name:'MAHMUD' AND name:'ABID AND name:'HAMID' AND name:'BID' AND
name:'HAMID' OR idnumber:123)
But I am not getting the result as per my requirement.

Salesforce - Apex - query accounts based on Activity History

Hey Salesforce experts,
I have a question on query account information efficiently. I would like to query accounts based on the updates in an activityHistory object. The problem I'm getting is that all the accounts are being retrieved no matter if there's "complete" activeHistory or not. So, Is there a way I can write this query to retrieve only accounts with activeHistory that has status="complete" and Type_for_reporting='QRC'?
List<Account> AccountsWithActivityHistories = [
SELECT
Id
,Name
,( SELECT
ActivityDate
,ActivityType
,Type_for_Reporting__c
,Description
,CreatedBy.Name
,Status
,WhatId
FROM ActivityHistories
WHERE Status ='complete' and Type_for_Reporting__c = 'QRC'
)
FROM Account
];
You have a WHERE clause on the histories but you still miss one on the Account level.
For example this would return only Accounts that have Contacts:
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT AccountId FROM Contact) // try with NOT IN too
With Activities it's trickier because they don't like to be used in WHERE in that way.
http://www.salesforce.com/us/developer/docs/officetoolkit/Content/sforce_api_calls_soql_select.htm
The following objects are not currently supported in subqueries:
ActivityHistory
Attachments
Event
EventAttendee
Note
OpenActivity
Tags (AccountTag, ContactTag, and all other tag objects)
Task
Additionally the fine print at the bottom of ActivityHistory definition is also a bit discouraging.
The following restrictions on users who don’t have “View All Data” permission help prevent performance issues:
In the main clause of the relationship query, you can reference only
one record. For example, you can’t filter on all records where the
account name starts with ‘A’; instead, you must reference a single
account record.
You can’t use WHERE clauses.
You must specify a limit of 499 or fewer on the number of rows returned in the list.
You must sort on ActivityDate in ascending order and LastModifiedDate in descending order; you can display nulls last. For
example: ORDER BY ActivityDate ASC NULLS LAST, LastModifiedDate DESC.
Looks like you will need multiple queries. Go for Task (or Event, depending for which the custom field is visible), compose a set of AccountIds and then query the Accounts?
Or you can manually filter through list from your original query, copying accounts to helper list:
List<Account> finalResults = new List<Account>();
for(Account a : [SELECT...]){
if(!a.ActivityHistories.isEmpty()){
finalResults.add(a);
}
}

Resources