I want to run a query where an item at a specific position in an array needs to be compared.
For example, consider the GeoJSON format for storing location data.
//sample document from collection user
{
name: "Some name",
location : {
type: "Point",
coordinates : [<Longitude>, <Latitude>]
}
}
How would I query users located at a specific longitude?
I cant seem to find anything in the documentation which can help me do the same.
Queries I have tried:
db.users.find({"location.coordinates[0]" : -73.04303})
Change your query to the following
db.users.find({"location.coordinates.0" : -73.04303})
Related
I have an array field in document named as IP which contains above 10000 ips as element.
for e.g.
IP:["192.168.a:A","192.168.a:B","192.168.a:C","192.168.A:b"...........]
Now i made a search query with some filter and i got the results but the problem is size of result very huge because of above field.
Now I want to fetch only N ips from array let say only 10 order doesn't matters.
So How do i do that...
update:
Apart from IP field there are others fields also and i applied filter on that field not on IP .I want whole document which satisfies filters .I just want to limit the number of elements in single IP fields.(Let me know if there is any other way apart from using script also ).
This kind of request could solve your problem :
GET ips/_search
{
"query": {
"match_all": {}
},
"script_fields": {
"truncate_ip": {
"script": {
"source": """
String[] trunc_ip = new String[10];
for (int i = 0; i < 10; ++i) {
trunc_ip[i]= params['_source']['IP'][i];
}
return trunc_ip;
"""
}
}
}
}
You can use scriptedFields for generating a new field from existing fields in Elastic Search. Details added as comments.
GET indexName/_search
{
"_source": {
"excludes": "ips" //<======= Exclude from source the IP field (change the name based on your document)
},
"query": {
"match_all": {} // <========== Define relevant filters
},
"script_fields": {
"limited_ips": { // <========= add a new scipted field
"script": {
"source": "params['_source'].ips.stream().limit(2).collect(Collectors.toList())" // <==== Replace 2 with the number of i.ps you want in result.
}
}
}
}
Note:
If you remove _source then only the scripted field will be the part of the result.
Apart from accessing the value of the field, the rest of the syntax is Java. Change as it suits you.
Apart from non-analyzed text fields, use doc['fieldName'] to access the field with-in script. It is faster. See the below excerpt from E.S docs :
By far the fastest most efficient way to access a field value from a
script is to use the doc['field_name'] syntax, which retrieves the
field value from doc values. Doc values are a columnar field value
store, enabled by default on all fields except for analyzed text
fields
By default ES returns only 10 matching results so I am not sure what is your search query and what exactly you want to restrict
no of elements in single ip field
No of ip fields matching your search results
Please clarify above and provide your search query to help further.
I'm having an elastic search index which has the following document sample in it :
{
"height": 2824,
"details": {
'gomathi':{'name':'gomathi','age':10},
'janu':{'name':'janu','age':20}
}
}
The data are pushed into elasticsearch dynamically from user. My goal is to fetch all documents that are containing name as gomathi.
Expected output:
Return documents having the 'gomathi' key in 'details' JSON object.
How to solve this?
Thanks in advance.
I assume details is a nested field in mapping. You could use inner_hits in a nested query for the requirement explained.
Please take a look at inner_hits and nested documentation.
So in my MongoDB Collection I have this structure:
"_id" : "Object("-----------")
"name" : "John Doe"
"tool" : {
"hammer" : {
"name" : "hammer 1",
"characteristics" : [
{
"length" : "9 inches"
},
{
"weight" : "4 pounds"
}
]
I know the data may seem a little strange but I can't put the actual data online so I had to input some dummy data. So essentially what I would like to do is be able to update the array that is nested within those objects. So I would like to be able to update the weight or add a new characteristic that I haven't previously entered into it. So for example, add in "metal" : "steel" as a new entry into the array. Currently I'm using a Rest API built in Node.js and Express.js to edit the db. When I was trying to figure out how to dig down this deep I was able to do it with an array at the highest level, however I haven't been able to figure out how to access an array when its embedded like this. So what I was wondering if anybody knew if it was even possible to edit an array this far down? I can post code from controller.js and server.js file if needed but I figured I'd see if it's even possible to do before I start posting it. Any help would be greatly appreciated!
You can use findAndModify to $push it into the array. You have to specify the path precisely though:
db.tools.findAndModify( {
query: { name: "John Doe"},
update: { $push: { tool.hammer.characteristics: {metal: "steel"} }
} );
I'm relatively new to mongodb, and I came into this company's set up that had the database already set up and running. It looks to me like the structure of this "array" isn't actually a proper array. They are saving info that I need in "offer_info_array" - which then has a nested array with an "offer id" which changes a lot between records, and then nested inside that is the info that I need to select. Here is an example of a record.
{
"_id" : ObjectId("52041af3bbf8057203000004"),
"offer_info_array" : {
"128" : {
"affid" : "68",
"s1" : "YJF"
}
},
"city" : "Cleveland",
"state" : "OH",
"zip" : "44111"
}
So from a whole db of records like this one, I need to find all records that have the "affid" of "68" - I realize this database is not structured correctly, but there's not much I can do about that for records that already exist. The "128" is the offer id that varies from record to record.
If anyone has any insight and can help me out with this, I would greatly appreciate it. Thank you!
You can use $where operator which accepts JavaScript function:
db.items.find({$where: function() {
for(var key in obj.offer_info_array)
if(obj.offer_info_array[key].affid == 68)
return true;
return false; }})
This function looks for properties of offer_info_array object and gets value of property by key. Then we verify if property value has affid property equal to 68. If yes, we return true which means objects matches our query. If there is no properties with affid equal to 68, we return false.
Keep in mind, that $where operator do not use indexes.
Let's say I have the following document schema in a collection called 'users':
{
name: 'John',
items: [ {}, {}, {}, ... ]
}
The 'items' array contains objects in the following format:
{
item_id: "1234",
name: "some item"
}
Each user can have multiple items embedded in the 'items' array.
Now, I want to be able to fetch an item by an item_id for a given user.
For example, I want to get the item with id "1234" that belong to the user with name "John".
Can I do this with mongoDB? I'd like to utilize its powerful array indexing, but I'm not sure if you can run queries on embedded arrays and return objects from the array instead of the document that contains it.
I know I can fetch users that have a certain item using {users.items.item_id: "1234"}. But I want to fetch the actual item from the array, not the user.
Alternatively, is there maybe a better way to organize this data so that I can easily get what I want? I'm still fairly new to mongodb.
Thanks for any help or advice you can provide.
The question is old, but the response has changed since the time. With MongoDB >= 2.2, you can do :
db.users.find( { name: "John"}, { items: { $elemMatch: { item_id: "1234" } } })
You will have :
{
name: "John",
items:
[
{
item_id: "1234",
name: "some item"
}
]
}
See Documentation of $elemMatch
There are a couple of things to note about this:
1) I find that the hardest thing for folks learning MongoDB is UN-learning the relational thinking that they're used to. Your data model looks to be the right one.
2) Normally, what you do with MongoDB is return the entire document into the client program, and then search for the portion of the document that you want on the client side using your client programming language.
In your example, you'd fetch the entire 'user' document and then iterate through the 'items[]' array on the client side.
3) If you want to return just the 'items[]' array, you can do so by using the 'Field Selection' syntax. See http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection for details. Unfortunately, it will return the entire 'items[]' array, and not just one element of the array.
4) There is an existing Jira ticket to add this functionality: it is https://jira.mongodb.org/browse/SERVER-828 SERVER-828. It looks like it's been added to the latest 2.1 (development) branch: that means it will be available for production use when release 2.2 ships.
If this is an embedded array, then you can't retrieve its elements directly. The retrieved document will have form of a user (root document), although not all fields may be filled (depending on your query).
If you want to retrieve just that element, then you have to store it as a separate document in a separate collection. It will have one additional field, user_id (can be part of _id). Then it's trivial to do what you want.
A sample document might look like this:
{
_id: {user_id: ObjectId, item_id: "1234"},
name: "some item"
}
Note that this structure ensures uniqueness of item_id per user (I'm not sure you want this or not).