I'm trying to figure out a way to find related content on my Rails blog by utilizing the "name" field that I have. Is there any way to find closely related posts in the database based on similarity of the "name" field.
For example:
Post 1 name field = this-similarity-other-thing
and
Post 2 name field = this-similarity-something-else
Is there any way I can search and find "this-similarity" as being roughly the same in the string, thus being able to pull it from the database and allow it to be shown in the view as related content?
I'm not sure exactly what you're looking for in Rails, but this is how I would do it in SQL:
SELECT b.name
FROM blogs b
WHERE b.name LIKE 'this-similarity-%'
Perhaps the Rails syntax would be something like:
Post.where("name ILIKE 'this-similarity%'")
Of course, how you get the context of the post you're currently (what I hard-coded as 'this-similarity%') on will depend on your implementation details.
if you want to just match on a substring, you can use a wildcard
Post.where("name LIKE '%substring%'")
if you want to incorporate something more flexible, you can try to get more advanced with ransack and elasticsearch
Use SIMILAR TO instead of LIKE - it allows to work with regular expressions
names = ['first', 'second', 'third'].join('|') # it gives "first|second|third" string
similar = Post.where("name SIMILAR TO '%(#{names})%'")
Related
I had implement SearchKick in my rails app. That app holds all the feature of searching that a recruiter app can have. I had working on this app for last 2 years and my searching query is written well enough to hold the aggregated data and some conditional clauses as well.
Now I want to implement "mini-language"(Boolean Operator) that is supported by elastic search using query_string.
Query String Supported Boolean Operator:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax
I want to use query_String with my existing SearchKick query. I know I can use Advanced Search but for this I would have to replace my current SearchKick query with an ElasticSearch query. I don't want to do that because it is a big change for my project which is live and has 1000+ of users.
I just want to adjust query_string in seachKick query in some way without having to replace it with ES query.
Is this possible?
I have the same problem.
But, if I understood the situation correctly, Searchkick maintainers decided to not support current behavior.
They mentioned it here:
https://github.com/ankane/searchkick/issues/97
and here:
https://github.com/ankane/searchkick/issues/1494
But, some workarounds may help you well enought.
You may do something like this:
Product.search body: {query: {query_string: {query: 'white shoes and water washable', default_field: 'product_description'}}}
I found it in this conversation:
https://github.com/ankane/searchkick/issues/1390#issuecomment-596657334
Or, you may just combine the needed fields into one for the search_data method. Which maybe even easier, but probably a more robust solution.
Please, see the reference below:
https://stackoverflow.com/a/51778715/2703618
We are using neo4j version 4.1.1,
and we have a graph that represents a structure of objects.
we support translation using nodes for translation and the connection between an object and a translation node is the object name and description.
for example:
(n:object)-[r:Translation]-(:ru)
means that on relationship r is the name and description of object n in russian.
In order to search by name and description we implemented a fullText index like that:
CALL db.index.fulltext.createRelationshipIndex("TranslationRelationshipIndex",["Translation"],["Name","Description"], { eventually_consistent: "true" })
We also support search for items in order to do it we are using the index to query and we have names like "UFO41.SI01V03":
CALL db.index.fulltext.queryRelationships('TranslationRelationshipIndex', '*FO41.SI0*') YIELD relationship, scoreĀ
but for names as shown above([0-9.*]) no results are returned
while results are returned for name like "ab.or"
Is there any one who knows how to make it work? I've tried all 46 analyzers available.
I know we can solve it just using match()-[r]-() where r.Name contains "<string>"
but we prefer a more efficient index-using solution to this problem.
stay safe!
and thanks in advance.
p.s if needed I can supply a few lines to recreate it locally just ask.
The analyzer will probably recognise words like ab.or differently than ab.or123 and consider them a single token in the first case and two tokens in the second case.
There is no analyzer that will really fit your needs except than creating your own.
You can however replace the . in your query with a simple AND, for eg :
CALL db.index.fulltext.queryNodes('Test', replace("*FO41.SI0*", ".", " AND "))
Will return you the results you're looking at.
Resources for creating your own analyser :
https://graphaware.com/neo4j/2019/09/06/custom-fulltext-analyzer.html
https://neo4j.com/docs/java-reference/current/extending-neo4j/full-text-analyzer-provider/
I am trying to fetch all cards that do not belong to the current user and it's title contains some keywords.
What I have so far after research is this code below.
#other_cards = Card.where(:user_id.ne => #temp_current_user, "title LIKE ?" => "%Business%").limit(10).order('created_at desc down_title asc')
But there are no records being returned even thought they are present.
I have also tried to skip the :user_id condition and all the limits and orders, resulting in this simple code to check if it will return anything
#other_cards = Card.where("title LIKE ?", "%Business%")
EDIT
I have also tried putting the conditions as an array suggested in the first comment. It also resulted in a error
EDIT 2
Attaching screenshot of running the query in rails console
LIKE syntax is part of SQL. MongoDB, and Mongoid, do not (directly) support SQL. The general rule of thumb is Ruby methods carry over from ActiveRecord to Mongoid, for example the following works with both AR and Mongoid:
Card.where(id: 123)
... but once you start to specify complex conditions in either keys or values, they are often specific to the database you are working with. In the code you provided, the :user_id.ne syntax will not be recognized by ActiveRecord, and Mongoid/MongoDB do not recognize title LIKE ?.
Your problem statement was:
I am trying to fetch all cards that do not belong to the current user and its title contains some keywords.
MongoDB has native full text search capability, which is a superior solution to trying to match keywords with regular expressions or SQL LIKE operators. MongoDB has good documentation on full text searches here. The Ruby driver has further documentation, and examples, for how to use full text search here. Mongoid does not currently have documentation for full text search (there is an in progress pull request to add it here) but the gist of it is to combine the driver documentation referenced earlier with the documentation here for how to work with indexes in Mongoid in general.
I would like to use Elasticsearch to analyze data and display it to the user.
When a user views a record for a model, I want to display a list of 'similar' records in the database for that model, and the percentage of similarity. This would match against every field on the model.
I am aware that with the Searchkick gem I can use a command to find similar records:
product = Product.first
product.similar(fields: ["name"], where: {size: "12 oz"})
I would like to take this further and compare entire records (and eventually associations).
Is this feasible with Elasticsearch / Searchkick in Rails, or should I use another method to analyze the data?
There is a feature built exactly for this purpose in Elasticsearch called more_like_this. The documentation for the mlt query goes into great details about how you can achieve exactly what you want to do.
The content you provide to the like field will be analyzed and the most relevant terms for each field will be used to retrieve documents with as many of those relevant terms. If you have all your records stored in Elasticsearch, you can use the Multi GET syntax to specify a document already in your index as content of the like field like this:
"like" : [
{
"_index" : "model",
"_type" : "model",
"_id" : "1"
}
]
Remember that you cannot use index aliases when using this syntax (so you'll have to do a document lookup first if you are not sure which index your document is currently residing in).
If you don't specify the fields field, all fields in the source document will be used. My suggestion to avoid bad surprises, is to always specify the list of fields you want your similar documents to match.
If you have non-textual fields that you want to match perfectly with the source document, you might want to consider using a bool query, programmatically creating the filter section to limit documents returned by the mlt query to only a filtered subset of your entire index.
You can build these queries in Searchkick using the advanced search feature, manually specifying the body of search requests.
Read up on using More Like This Query. This is the query produced by product.similar(). It operates only on text fields. If you also want to compare numeric or date fields, you'll have to incorporate these rules into a scoring script to do what you're asking.
I want to do the opposite of this:
image_name = "blah"
Pipe.where("LOWER(name) like ?", "%#{image_name.downcase}%") (this would find a Pipe named 'blahzzz`)
What I want is the opposite, where I have a pipe named ah and given image_name = "blah", I want to be able to find that Pipe. How would I accomplish this?
i think what you are looking for is a functionality of a full-text search index like lucene. search for sunspot or tire, they provide bindings for solr and elasticsearch. those are the most common full-text servers out there.
if you want to find partials of text, there is a feature called n-gram that allows you to find matching parts or substrings. i think that would be the way to go on a larger scale.
if you have just one place, where you are going to implement this functionality and your database is not too large, you can mimic the behavior in a relational database by combining a lot of OR LIKE queries and providing substrings of the input.