I'm building a web application over Node.js and MongoDB which is based on geolocated points.
The document is something like this:
{ name: ""
keywords: [Array of strings]
location: {lng: double, lat: double }
}
I am wondering how could I use find() to find documents that are near from a coordinate but, in addition, are coincident with any of he keywords in the keywords array.
Imagine that keywords are: ["restaurant", "bar", "coffee"]
I've looked into 2d Index, but the secondary index must be a string. It can't be an array of strings.
The problem is that a document could have more than one keyword (or category) so I can't use a simple string to query them
How would you implement this?
Thanks!
What version of mongo? It looks like this was added in 2.4.0: SERVER-8457
Related
I want to get the field of a MongoDB collection where the field is a substring of a longer string.
Real example:
str = 'forest'
MongoDB Collection:
{id: 1, name: est}
{id: 2, name: ab}
I want to get the first item because est is a substring of forest
One way to do this very efficiently is with MongoDB's full-text search. This requires defining a text index type on that particular field.
If you wanted matches that strictly contained your query, check out the exact-phrase operator.
Using AQL (preferably in the ArangoDB WebUI), is it possible to generate a random string or letters and numbers similar to this: 4EKH5G3AN6HH?
If not, what is another way to do it without doing it in application code?
https://docs.arangodb.com/3.0/AQL/Functions/String.html#randomtoken
RANDOM_TOKEN(8) // "zGl09z42"
then you can apply https://docs.arangodb.com/3.0/AQL/Functions/String.html#upper
UPPER(RANDOM_TOKEN(8)) // "ZGL09Z42"
Great answer from sevcik.tk
Just in case, you can generate documents full of random data like that:
FOR i IN 1..300000
INSERT {
code: CONCAT("t", i),
name: RANDOM_TOKEN(32),
article1: RANDOM_TOKEN(10),
article2: RANDOM_TOKEN(20)
} IN batchtest
And there is link to useful functions:
https://www.arangodb.com/docs/stable/aql/functions-string.html#random_token
My index has a string field containing a variable length random id. Obviously it shouldn't be analysed.
But I don't know much about elasticsearch especially when I created the index.
Today I tried a lot to filter documents based on the length of id, finally I got this groovy script:
doc['myfield'].values.size()
or
doc['myfield'].value.size()
both returns mysterious numbers, I think that's because of the field got analysed.
If it's really the case, is there any way to get the original length or fix the problem, without rebuild the whole index?
Use _source instead of doc. That's using the source of the document, meaning the initial indexed text:
_source['myfield'].value.size()
If possible, try to re-index the documents to:
use doc[field] on a not-analyzed version of that field
even better, find out the size of the field before you index the document and consider adding its size as a regular field in the document itself
Elasticsearch stores a string as tokenized in the data structure ( Field data cache )where we have script access to.
So assuming that your field is not not_analyzed , doc['field'].values will look like this
"In america" => [ "in" , "america" ]
Hence what you get from doc['field'].values is a array and not a string.
Now the story doesn't change even if you have a single token or have the field as not_analyzed.
"america" => [ "america" ]
Now to see the size of the first token , you can use the following request
{
"script_fields": {
"test1": {
"script": "doc['field'].values[0].size()"
}
}
}
I have two objects:
{
genre: ['music', 'movie']
}
and
{
genre: ['movie', 'music']
}
and my query is:
db.test.find({genre :{ $elemMatch:{ $in : ['movie']}}})
and it only gives me the second object. Why? I want to get all the docs that contain a specific genre in their arrays no matter where in the array. How can I do this?
You need neither $elemMatch nor $in in this case. A simple field:value will match documents where field is an array and any one of the values in that array is value. That means
db.test.find({genre :'movie'});
will suffice.
The array query operators are required in more complex situations.
$in is needed when you have a list of possible values and want documents where any of them is found (so db.test.find({genre : { $in:['movie']} }); would work, but would be needlessly convoluted)
$all works like $in but requires that all provided elements are in the array
$elemMatch is a bit more complex. It is required when you want to use multiple operator-conditions (like $gt or $lt) but want only those documents where one array entry matches all the conditions. Without the $elemMatch operator, you get results where each condition is met by at least one array entry, but not necessarily all by the same entry.
Remember db.test.find() in general returns you cursor object. You can access all doc as follows:
entry = db.test.find({genre :{ $elemMatch:{ $in : ['movie']}}})
for doc in entry:
print(doc)
I have a collection in a mongo store where each element has a name attribute. I've sorted it alphabetically by doing
sort({'name': 1})
but now I would like to find only the elements beginning with some letter, say t. So a desired result might return:
[{name: tam}, {name: tom}, {name: tommy}]
How would I go about constructing a query like this?
You need to use regex. In your case it will look like this:
db.collection.find({
name: /^t/
});