How to apply test and set condition in yql query - vespa

Below is the search definition of my document. I have field "expire" which is a timestamp in my document.Now I want to search documents using yql query if isActive="1" and test.expire - now() > 0.Can I achieve this by query?
search test {
document test {
field Id type string {
indexing: index|summary
}
field isActive type string {
indexing: index|summary
}
field expire type long {
indexing: index | summary
}
field detail type string {
indexing: summary
}
}
}
If yes then what would be my query? How can I apply condition in my query?Please help

YQL for this is
?query=select * from test where (isActive contains "1" and expire > nowTimestamp);&type=yql
You cannot use now() so you need to insert the timestamp yourself.
You could also construct the query in a Searcher component (bypassing the need to construct a YQL string).

Related

Searching non-primitive types within a struct

I need to search within a an array nested in another array. Let's say I have the following document
schema foos {
document foos {
struct foo {
field bars type array<string> {}
}
field baz type string {
indexing: summary
}
field foos type array<foo> {
indexing: summary
struct-field bars { indexing: attribute } // breaks due to non-primitive typing
}
}
}
I need to be able to search within the bars field or at least access that field within a rank-profile whilst also being able to search based on baz. My first thought at a solution would be to structure it as follows:
schema foos {
document foos {
field id type string {
indexing: summary
}
field baz type string {
indexing: summary | attribute
}
field foos type array<reference<foo>> {
indexing: summary
}
}
}
schema foo {
document foo {
field foos_ref type reference<foos> {
indexing: attribute
}
field bars type array<string> {
indexing: summary | index
}
}
import field foos_ref.baz as baz {}
}
This would allow me to search within the foo cluster then get the corresponding foos reference, but the overall goal is to provide the user a list of foos documents which would require multiple searches from the list of returned foo documents resulting in slow searches overall.
If there is a recommended way to handle situations like these, any help would be appreciated. Thank you.
First, note that a reference field used for parent child relationships can only be single value and not an array (https://docs.vespa.ai/documentation/reference/schema-reference.html#type:reference). The reference field is specified in the child type to reference the parent. The schemas can be defined as follows, where foos is the parent type and foo is the child type:
schema foos {
document foos {
field id type string {
indexing: summary | attribute
}
field baz type string {
indexing: summary | attribute
}
}
}
schema foo {
document foo {
field foos_ref type reference<foos> {
indexing: attribute
}
field bars type array<string> {
indexing: summary | index
}
}
import field foos_ref.baz as foos_baz {}
import field foos_ref.id as foos_id {}
}
Now you can search for foo documents using the fields bars and foos_baz in the query. Use grouping (https://docs.vespa.ai/documentation/grouping.html) on the foos_id field to structure the result around the foos documents instead. This is handled in a single query request.

sosl query wildcard not returning correct results

I have a function that uses a sosl query:
private List<Product2> runSoslToExecute() {
List<List<Product2>> searchResults = [FIND :query IN ALL FIELDS RETURNING Product2 (Id, Name)];
List<Product2> results = new List<Product2>();
for(Product2 p : searchResults[0]) {
results.add(p);
}
return results;
}
If I search for "AB*" then I also get results that include "1AB...". I thought the "*" wildcard only searches in the middle and end of the search and not at the beginning? Is there a way to run the sosl search so it only searches "AB" at the beginning?
Thanks for any help.
You could use like, for example,
Select Id, Name from Account where Name like 'AB%'

how to order groups by count in solr

I'm wondering how to order groups in a Solr result. I want to order the groups by numFound. I saw how to order the groups by score here, but that didn't seem to actually make a difference in the examples I looked at, and isn't exactly what I wanted.
In the xml you can see the number per group as numFound and that is what I want to sort the groups by, so for example I could see the largest group at the top.
<arr name="groups">
<lst>
<str name="groupValue">top secret</str>
<result name="doclist" numFound="12" start="0">
...
Any tips appreciated! Thanks!
This is an old question, but it is possible with two queries.
First query: bring back the field you're grouping by as a set of facets for your navigation state. You can limit the number of records returned to 0 here: you just need the facets. The number of facets you return should be the size of your page.
group_id:
23 (6)
143:(3)
5:(2)
Second query: Should be for the records, so no facets are required. The query should be an OR query for the facet field values returned from the first query. (group_id:23 OR group_id:143 OR group_id:5 and so on) and be grouped by the id you are used for grouping.
Sorting: reorder the records from query 2 to match the order from query 1.
That'll do it, with the proviso that I'm not sure how scalable that OR query will be. If you're looking to paginate, remember that you can offset facets: use that as the mechanism instead of offseting the records.
Sorting on the numFound is not possible as numFound is not an field in Solr.
Check the discussion mentioning it not being supported and I did not find a JIRA open for the issue as well.
Not possible since the last time I looked into this.
you can sort by using fields
consider an Example :
If you have 5 FACETS and COUNT associated with it.
Then you can sort by using the COUNTS of each fields.
It can be applicable to normal/non-facets fields .
public class FacetBean implements Category,Serializable {
private String facetName; //getter , setters
private long facetCount; // getter , setters
public FacetBean(String facetName, long count,) {
this.facetName = facetName;
this.count = count;
}}
Your calling method should be like this
private List<FacetBean> getFacetFieldsbyCount(QueryResponse queryResponse)
{
List<FacetField> flds = queryResponse.getFacetFields();
List<FacetBean> facetList = new ArrayList<FacetBean>();
FacetBean facet = null;
if (flds != null) {
for (FacetField fld : flds) {
facet = new FacetBean();
facet.setFacetName(fld.getName());
List<Count> counts = fld.getValues();
if (counts != null) {
for (Count count : counts) {
facet.setFacetCount(count.getCount());
}
}
facetList.add(facet);
}
}
Collections.sort(facetList,new Comparator<FacetBean>() {
public int compare(FacetBean obj1, FacetBean obj2) {
if(obj1.getFacetCount() > obj2.getFacetCount()) {
return (int)obj1.getFacetCount();
} else {
return (int)obj2.getFacetCount();
}
}
});
return facetList;
}
In The same URL They have mentioned something like.
sort -- >ex : For example, sort=popularity desc will cause the groups to be sorted according to the highest popularity doc
group.sort -- > you can apply your field here .
Hope it helps.

Custom Query Component - How to get "score" from document id?

I'm writing several Solr Custom Query Components.
Each component run different kinds of queries:
Component A: does a group by query field A
Component B: does a group by on a different fild B
Each component will send it's the documents from it's result to the next component.
In my "process" function, I'm donig the following after the result is set by grouping:
IndexSchema schema = searcher.getSchema();
DocListAndSet s = result.getDocListAndSet();
DocSet s3 = s.docSet;
DocIterator dit = s3.iterator()
while (dit.hasNext())
{
SolrDocument doc = new SolrDocument();
int docid = dit.nextDoc();
//float score = dit.score();<--This does not get the score
Document luceneDoc = searcher.doc(docid);//get the document using the doc id
for( Fieldable field : luceneDoc.getFields())
{
SchemaField sf = schema.getField( field.name() );
doc.addField( field.name(), sf.getType().toObject( field ) );
......
}
And then iterating through the Set and createing SolrDocument.
The SolrDocumentes are entered into a SolDocumentList and end I send it off to the next Component:
rb.req.getContext().put("TAG", list);
I also want to add a field called "score" SolrDocument, this field will contain the actual score. I've tried getting the score using:
float score = dit.score()
But the above does not get the score of the document. How do I get the "score" of the document using the document id?
Is there a particular reason you are getting the docSet instead of the docList?
I would try (condensing a bit) getting s.docList.iterator() instead of s.docSet.iterator(). The latter states specifically in the documentation here that you can't get meaningful scores from it, where the docList states it may contains valid scores.
Well you have to set GET_Scores in getDocList(query,List,Lsort,offset,maxnoofdocs,1)
Here
`
query is your query obj
List<Query> your filters could be null
lsort could be null
offset
maxnoofdocs integer
1 means get score with documents`

How to query SOLR for empty fields?

I have a large solr index, and I have noticed some fields are not updated correctly (the index is dynamic).
This has resulted in some fields having an empty "id" field.
I have tried these queries, but they didn't work:
id:''
id:NULL
id:null
id:""
id:
id:['' TO *]
Is there a way to query empty fields?
Thanks
Try this:
?q=-id:["" TO *]
One caveat! If you want to compose this via OR or AND you cannot use it in this form:
-myfield:*
but you must use
(*:* NOT myfield:*)
This form is perfectly composable. Apparently SOLR will expand the first form to the second, but only when it is a top node. Hope this saves you some time!
According to SolrQuerySyntax, you can use q=-id:[* TO *].
If you have a large index, you should use a default value
<field ... default="EMPTY" />
and then query for this default value.
This is much more efficient than q=-id:["" TO *]
You can also use it like this.
fq=!id:['' TO *]
If you are using SolrSharp, it does not support negative queries.
You need to change QueryParameter.cs (Create a new parameter)
private bool _negativeQuery = false;
public QueryParameter(string field, string value, ParameterJoin parameterJoin = ParameterJoin.AND, bool negativeQuery = false)
{
this._field = field;
this._value = value.Trim();
this._parameterJoin = parameterJoin;
this._negativeQuery = negativeQuery;
}
public bool NegativeQuery
{
get { return _negativeQuery; }
set { _negativeQuery = value; }
}
And in QueryParameterCollection.cs class, the ToString() override, looks if the Negative parameter is true
arQ[x] = (qp.NegativeQuery ? "-(" : "(") + qp.ToString() + ")" + (qp.Boost != 1 ? "^" + qp.Boost.ToString() : "");
When you call the parameter creator, if it's a negative value. Simple change the propertie
List<QueryParameter> QueryParameters = new List<QueryParameter>();
QueryParameters.Add(new QueryParameter("PartnerList", "[* TO *]", ParameterJoin.AND, true));
you can do it with filter query
q=*:*&fq=-id:*
A note added here, to make the field searchable first, it needs the field type in SOLR schema set to "indexed = true". Then you can use "field_name:*" for string type and "field_name:[* TO *]" for numeric type.

Resources