Laravel elastic search display relevant data in top order - laravel

This is regarding to order the elastic search results in custom order.
I have city ids(integers) in my elastic search index, based on the user city selection the elastic search should happen.
For example:
Consider the id of Chennai is 1 & Mumbai is 2
If we have 10 records for Chennai and 20 records for Mumbai in elastic index. If the user choose Chennai, we should display the 10 records belongs to Chennai in top order and then display the remaining items.
If the user choose Mumbai, we should display the 20 records belongs to Mumbai in top order and then display the remaining items.
I am using sleimanx2/plastic laravel package for search. Appreciate if anyone help me to achieve this.

Is there any specific reason that you wish to achieve this with elastic?
The mentioned case seems to me like something i would achieve with two queries. One for the promoted, let's call them results, and one that would match everything else, except those that belong to the first query.
Then I would go ahead and display them to their respective areas or whatever.
There might be a way to merge those queries together and get your results as buckets that you can later use to create your markup accordingly, but honestly I am not sure that there is a reason to do it like this.
I hope I do not misunderstand your question,
Best Regards.

Related

Visualization with Pipeline Aggregation in Kibana and Elasticsearch

I've been struggling around with some visualization in Kibana.
For this example I will be using data from kibana samples (kibana_sample_data_ecommerce).
So want I would like to do is a visualization that shows: how many customers did 1 order, how many customers did 2 orders, how many customers did 3 orders, and so on.
An example of visualization would be this:
Using a table visualization and aggregating for Terms in descending order I can get something like this:
On the left of the table we have the customer's name and on the right the count of orders the customer did.
I don't know what kind of aggregation should I use now so I can group the customers with same values into a new label. Something like, from this
to this
Btw I'm using kibana 7.2
Any suggestions and ideas are welcome.
Thank you!
Edit:
I want to be able to group customers with same results (nÂș of orders) under a new bucket (and if is possible with a custom label).
Go for Terms aggregation on order field while setting the Metric Aggregation as count.
Hope that answers your question.

Elasticsearch : search for sets of items instead of items

I created a website where I log users actions: visit page, download document, log in, etc. Each action is timestamped, attached to a user and indexed in Elasticsearch
I would like to recognize predefined patterns in thoses actions. eg:
find users who visited this page, this other page and downloaded 2 documents in the last 3 weeks
find users who logged in and visited at least 5 pages in the same day
The problem I have is I always used ES to find items that match criterias but never to find set of items.
How would you start to solve this problem ?
Thank you for your help.
For the second query I would suggest aggregations (like SQL GROUP BY): count the number of page visits aggregated per user and day.
And then add conditions on these aggregated results (like SQL HAVING)
To filter on aggregation results I found this (not tested or tried to understand:):
https://www.elastic.co/guide/en/elasticsearch/reference/master/search-aggregations-pipeline-bucket-selector-aggregation.html
Hope it helps

Good way to exclude records in SOLR or Elasticsearch

For a matchmaking portal, we have one requirement where in, if a customer viewed complete profile details of a bride or groom then we have to exclude that profile from further search results. Currently, along with other detail we are storing the viewed profile ids in a field (Comma Separated) against that bride or groom's details.
Eg., if A viewed B, then in B's record under the field saw_me we will add A (comma separated).
while searching let say the currently searching members id is 123456 then we will fire a query like
Select * from profiledetails where (OTHER CON) AND 123456 not in saw_me;
The problem here is the saw_me field value is growing like anything, is there any better way to handle this requirement? Please guide.
If this is using Solr:
first, DON'T add the 'AND NOT ...' clauses along with the main query in q param, add them to fq. This have many benefits (the fq will be cached)
Until you get to a list of values that is maybe 1000s this approach is simple and should work fine
After you reach a point where the list is huge, maybe it time to move to a post filter with a high cost ( so it is looked up last). This would look up docs to remove in an external source (redis, db...).
In my opinion no matter how much the saw_me field grows, it will not make much difference in search time.Because tokens are indexed inversely and doc_values are created at index time in column major fashion for efficient read and has support for caching from OS. ES handles these things for you efficiently.

Elasticsearch: group into buckets, reduce to one document per bucket, group these documents

I'm looking for a way how to compute the bounce rate of webpages with elastic search.
We collect data in the following simplified structure
{"id":"1", "timestamp"="2017-01-25:15:23", "sessionid"="s1", "page"="index"}
{"id":"2", "timestamp"="2017-01-25:15:24", "sessionid"="s1", "page"="checkout"}
{"id":"3", "timestamp"="2017-01-25:15:25", "sessionid"="s1", "page"="confirm"}
{"id":"4", "timestamp"="2017-01-25:15:26", "sessionid"="s2", "page"="index"}
{"id":"5", "timestamp"="2017-01-25:15:27", "sessionid"="s2", "page"="checkout"}
{"id":"6", "timestamp"="2017-01-25:15:26", "sessionid"="s3", "page"="product_a"}
{"id":"7", "timestamp"="2017-01-25:15:28", "sessionid"="s3", "page"="checkout"}
For this sample the result of the analysis should be:
2/3 of the users get lost at the checkout page.
1/3 of the users get lost at the confirm page
More formally, I'm looking for a generic approach how to implement the following algorithm in an elastic query:
group documents by a field
sort each group (bucket) by a second field and reduce to the topmost document
group all these remaining documents by a third field
sort groups by number of documents
My first attempt was to solve this with a terms aggregation followed by a top_hits aggregation and finally use a
terms_pipeline aggregation to group the pages.
(simplified aggregation structure)
aggs
terms
field: sessionid
aggs
top_hits
sort:timestamp desc
size: 1
terms_pipeline
bucket_path: terms>top_hits
field: page
... but unfortunately there is no such thing like a terms_pipeline aggregation. My bad.
Any ideas for an alternative approach?
Maybe I misunderstood something but if you are willing to know where your users are bouncing, since all pages are in a sequence, you could simply have a terms aggregation on the page field (to know which pages were visited) and a cardinalityone on the sessionid field (to know how many different unique sessions you have). In this case, cardinality(sessionid) would yield 3.
Then again, since all pages are in a sequence, I think you don't really need to know what happened within a given session.
In your example, from the terms(page) aggregation, you'd know that 3 users landed on the checkout page but only one went to the confirm one. Using the cardinality of the sessions, this implicitly means that 2 users (3 total sessions - 1 confirm page hit) bounced on the checkout page.

How to tabulate data , without doing any aggregation in Kibana?

How can I tabulate data from events in kibana, without doing any aggregations?
I want to prepare a table containing 3 columns:
Hotel Name
No. of Rooms
Zipcode of Hotel
I want to extract this info from events and populate the table with above three values. How can I do this in Kibana?
You may be able to accomplish this by saving a search in the discover application and adding it to a dashboard directly (skipping the visualize step).
At the top of the "Add" panel in dashboard there is a "Searches" tab:
This tab lists all of the searches that you've saved from Discover and allows you to visualize the raw field values of documents as a table.
Hope that helps!
You can't make a table without aggregating, but (depending on your data) you may be able to get what you want by aggregating first on hotel name (Terms, Field=name, Order=Top, Size=100) then by zip code (Terms, Field=zip). The aggregation is so narrow that there is never more than one hotel in any given bucket.
Then use metric of Sum of number of rooms.
This assumes there are no two same-named hotels in the same zip code. If there are, you'll need to add a third column with some unique identifier.
I tried this using the following mapping
{"name": {"type":"string","index":"not_analyzed"},
"number-of-rooms":{"type":"integer"},
"zip": {"type":"string","index":"not_analyzed"}}
It worked fine, with the drawback that the table column header labels are "Top 100 name", "Top 100 zip" and "Sum of number-of-rooms", which isn't very user friendly.

Resources