How to achieve autocomple query with query dsl (elasticsearch)? - autocomplete

How can i achieve autocompleter search/results withh query dsl (QueryBuilder) ?
(api link)
Want to achieve search like :
search keyword "John D"
result:
"John Daa"
"John Derm"
"John Deerms"
I tried to use "match" and "multi match" with "phrase_prefix" type, it almost did the job but there is something wrong, since results are :
for keyword "John D" - only "John Daa" is shown, other two are missing, do not understand this part much.
for keyword "John De" - Shown are "John Derm", "John Deerms" which is OK .

The problem you have is solved by completion suggester.

Related

Firebase observe key contains

I'd like to fetch snapshot which contains typed text. For example node look like this
"Team": {
"Yankees": {
"uid1": "name",
"uid2": "name"
},
"Angels": {
"uid1": "name"
"uid3": "name"
}
and if user typed yan in search bar then I want to fetch "Yankees" snapshot. I saw some document and stack over flow post and tried like so
ref.child("Team").queryStarting(atValue: "yan").queryEnding(atValue: "yan\u{f8ff}").observe
but it doesn't work. How can I do this? Thank you!
Firebase searches are case sensitive. Since your key starts with an uppercase Y, the query only matches if it also does that:
ref.child("Team")
.queryOrderedByKey()
.queryStarting(atValue: "Yan")
.queryEnding(atValue: "Yan\u{f8ff}").observe
I also queryOrderedByKey() to be explicit about what you want to order/filter on.
If you want to allow case-insensitive filtering, the typical approach is to add a property with the all-lowercase value to each team:
"Team": {
"Yankees": {
"teamNameForSearch": "yankees",
"uid1": "name",
"uid2": "name"
},
"Angels": {
"teamNameForSearch": "angels",
"uid1": "name"
"uid3": "name"
}
Now you can search with:
ref.child("Team")
.queryOrdered(byChild: "teamNameForSearch")
.queryStarting(atValue: "yan")
.queryEnding(atValue: "yan\u{f8ff}").observe
A final note is that both approaches only do so-called prefix matches: they find teams whose name starts with what the user typed. If you want a contains operation (as the title of your question suggests), you will have to look beyond Firebase for a solution. For more on that, see Kato's answer here: Firebase query - Find item with child that contains string
You need to change the db to this:
"Team": {
"randomid": {
"team":"Yankees",
"uid1": "name",
"uid2": "name"
},
"randomid": {
"team":"Angels"
"uid1": "name"
"uid3": "name"
}
and now you can do this:
ref.child("Team").queryOrdered(byChild: "team").queryStarting(atValue: "Yan").queryEnding(atValue: "Yan\u{f8ff}").observe
First in your query above, you need to use queryOrdered() to know which child you want to order.
Also in your database the node Team is not equal to anything, it is a parent node that has child nodes.
So to fix this, the node Team needs to be equal to a value(like in the database in this answer) so you will be able to order it and use queryStarting and queryEnding on it.

Displaying embedded data in Mongo DB with Python

I am working on a project with Flask and Mongo DB and I want to display some embedded documents. I am not really getting error messages but the data is not displaying how I want it to. Currently, my documents look like this:
{ "_id" : ObjectId("590639009103ad05fd8555dc"),
"comments" : [ { "comment" :
"Hello World" } ],
"age" : 23,
"name" : "Mike" }
Now, I want to display data that will show the name and the comments that the individual said. I want something like this: Mike, says the following: 'Hello World'
My code looks like this:
thoughts = person.show()
for thought in thoughts:
print(thought["name"], "says the following:", thought["comments"])
where the show() method looks like this:
def show(self):
thoughts = self.db.people.find()
return thoughts
Now for the most part almost everything works how I want it to. When I run my code I get this:
Mike says the following: {'comment': 'Hello World'}
What I need to do is to dig further down into the embedded document to display:
Mike, says the following: 'Hello World'
I have tried the following:
for thought in thoughts:
print(thought["name"], "says the following:",
thought["comments.comment"])
which gets me the following error message: KeyError: 'comments.comment'
I then tried the following:
for thought in thoughts:
print(thought["name"], "says the following:", thought["comments"]
["comment"])
which gives me the following error:
TypeError: list indices must be integers, not str
Thus, I am somewhat stuck how to pull out each comment. Any help would be appreciated.
thought["comments"] is a list of dicts. you want the comment field of the first item on the list, thus:
print(thought["comments"][0]["comment"])

declarative data structure query language

I'm having difficulty describing a sort of query language that I figure must exist and have a name.
Simply, you describe the data you want to receive as a data structure of paths to values and any transformations, constraints, etc.
For example, requesting this:
{:query {:title
:content
:fullname (join [:author.firstname :author.lastname] " ")
:meta {:date-created
:date-updated
:date-published}}
:limit 10
:order-by :title}
would return a list of results like:
[
{:title "dummy title 1"
:content "lorem ipsum"
:author "Jane Doe"
:meta {:date-created 2016-01-01
:date-updated 2016-01-02
:date-published 2016-01-02}}
{:title "dummy title 2"
:content "ipsum lorem"
:author "John Doe"
:meta {:date-created 2016-01-01
:date-updated 2016-01-02
:date-published 2016-01-02}}
...
]
Datalog type queries and even MongoDB queries have a similar feel but does this type of querying have a name or fit some design pattern I can better search the internet for?
I've just come across Facebook's GraphQL that seems to serve this purpose.
https://code.facebook.com/posts/1691455094417024/graphql-a-data-query-language/
And the Python Graphene library has Django support.
There is a repo with links to the various implementations: https://github.com/chentsulin/awesome-graphql

How to find all the comment of a single author for the given data-set in mongodb?

Let's say I have a blog dataset which looks like ths
{
"_id" : "abcde",
"author" : "xyz",
"body" : "this is test body",
"date" : "xyz",
"tags" : ["tag1","tag2"],
"comments":[
{ "body": "comment1",
"email": "email1",
"author" :"author1"
},
{ "body": "comment2",
"email": "email2",
"author" :"author2"
}
]
}
Here each document is representing a blog post. Each blog post can have multiple comments, but one my one user. Let's say I have to find all comments made by a particular author. What will be the query for that?
One approach would be to unwind comments, then group by comments.author and push comments.body.
However, Can it be done without aggregation pipeline, just by using find? Because I think I am supposed to do it just by find. Can anyone help me with this?
You can use dot notation to query against an array of subdocuments.
Your query would look something like this:
db.blog_posts.find({"comments.author": "author1"});
This will return all documents which contain subdocuments that have an author value of author1. The results will be the entire post document, so you might want to specify the fields that you want returned. This is called query projection.
db.blog_posts.find({"comments.author": "author1"});
To specify what fields you want, add an extra object as the second parameter to your .find() function:
db.blog_posts.find({"comments.author": "author1"}, {"comments": 1} );
Now the resulting documents will only contain the _id field and the comments field.
Keep in mind that you are actually querying the blog posts collection so your returned results will still be the blog posts - but only the ones where the specified author has commented on.
A simple way to take the next step and extract only the comment objects might look something like this:
var author = 'author1';
var comments = [];
db.blog_posts.find(...).forEach(function(doc){
var post_comments = doc.comments;
for (var i=0; i<post_comments.length; i++){
if (post_comments[i].author == author){
comments.push(post_comments[i]);
}
}
});
Here is the relevant documentation page:
http://docs.mongodb.org/manual/tutorial/query-documents/#array-of-embedded-documents
Match a Field Without Specifying Array Index
If you do not know the index position of the document in the array, concatenate the name of the field that contains the array, with a dot (.) and the name of the field in the embedded document.

Mongodb query by regular expression

I use Mongodb to store list of locations over the world, with more than 2M records. Each record is an object like this:
{ "_id" : ObjectId("4e5b339feee76320ab26f930"), "city" : "New York", "longitude" : -87.2008333, "latitude" : 30.8383333, "country_code" : "US", "country_name" : "United States" }
I want to perform the search to get out all "CITIES" contain "New York", it took me about 10 seconds to have the result (it is unacceptable in my web system). I have indexed the "city" using ensureIndex() function, but the query is still slow.
Here is my query:
db.locations.find({"city": { "$regex": "(New York)", "$options": 'i' }})
I guess the problem is the "regular expression". Can you suggest me a solution for this to get the query result within 2-3 seconds (I have more than 4M records in MySQL, the similar query took me only 1-2 seconds - with indexes).
Thanks and regards.
You can't search with contain operation in mongodb without using regexp or javascript (they are slow, because of work without index).
I can suggest to store additional city in lower case and search by full match. If you want 'contains' and fast speed you should use some another full text search engines like solr or lucene.
I recommends use multi keys.
example:
{ title : "this is fun" ,
_keywords : [ "this" , "is" , "fun" ]
}
then you can use
db.articles.findOne( { _keywords: "this" } )
this will be more faster
Mongo doesn't use index for regexp when it search with case insensitive. I suggest you to store your field with uppercase or lowercase and use same for search.
Instead of search containing if you search start with like below
db.locations.find({"city": { "$regex": /^New York/}})
your query will return fast .
for more info RegularExpressions