Filtering sub-documents


(Hugo) #1

Hi all,

I have a document structure like this:

{
"_index": "building",
"_type": "info",
"_source": {
"name": "First building",
"security_level": 1,
"state": 1,
"description": "first area obs",
"floors": [
{
"description": "First Store",
"name": "First floor",
"security_level": 2
},
{
"description": "Second Store",
"name": "Second floor",
"security_level": 1
}
]
}
}

and I want to search by floor name/description and/or building
name/description but omitting the results if the user does not have the
correct security level.
For instance if I try to find "First" and my security_level is 0 I should
not get any hit, but if my security level is 1 or 2 I should get one hit.
Also if I try to find "Store" and my security_level is 0 I should not get
any hit, but if my security level is 1 or 2 I should get one hit.

I've tried using the following query (for a user with security_level equal
to 1) but is does not work because it filters all documents that have one
or more floors.security_level equal to 2, even if there are other
floors.security_level with 0 or 1 that match the other criteria.

{
"query" : {
"filtered" : {
"query" : { "match_all" : {} },
"filter" : {
"and" : [
{ "or" : [
{ "prefix" : { "name" : "Store" } },
{ "prefix" : { "description" : "Store" } },
{ "prefix" : { "floors.name" : "Store" } },
{ "prefix" : { "floors.description" : "Store" } }
]},
{ "not": { "filter" : { "term" : { "security_level" : 2 } } } },
{ "not": { "filter" : { "term" : { "floors.security_level" : 2 } } } }
]
}
}
}
}

Can anyone please help me?

Thanks.
Best regards,
Hugo


(Shay Banon) #2

You need to use nested mapping to treat inner array of objects as a "self sufficient" document, and then use nested filter / query. See more here: http://www.elasticsearch.org/guide/reference/mapping/nested-type.html.

Also, note you use things like prefix filter, and that part is not analyzed. So, if you index desc as "First Store", the terms created are "first" and "store" (by the default standard analyzer), which means using prefix filter (or query) with "First" will not match anything.

On Tuesday, March 6, 2012 at 7:59 PM, Hugo wrote:

Hi all,

I have a document structure like this:

{
"_index": "building",
"_type": "info",
"_source": {
"name": "First building",
"security_level": 1,
"state": 1,
"description": "first area obs",
"floors": [
{
"description": "First Store",
"name": "First floor",
"security_level": 2
},
{
"description": "Second Store",
"name": "Second floor",
"security_level": 1
}
]
}
}

and I want to search by floor name/description and/or building name/description but omitting the results if the user does not have the correct security level.
For instance if I try to find "First" and my security_level is 0 I should not get any hit, but if my security level is 1 or 2 I should get one hit.
Also if I try to find "Store" and my security_level is 0 I should not get any hit, but if my security level is 1 or 2 I should get one hit.

I've tried using the following query (for a user with security_level equal to 1) but is does not work because it filters all documents that have one or more floors.security_level equal to 2, even if there are other floors.security_level with 0 or 1 that match the other criteria.

{
"query" : {
"filtered" : {
"query" : { "match_all" : {} },
"filter" : {
"and" : [
{ "or" : [
{ "prefix" : { "name" : "Store" } },
{ "prefix" : { "description" : "Store" } },
{ "prefix" : { "floors.name (http://floors.name)" : "Store" } },
{ "prefix" : { "floors.description" : "Store" } }
]},
{ "not": { "filter" : { "term" : { "security_level" : 2 } } } },
{ "not": { "filter" : { "term" : { "floors.security_level" : 2 } } } }
]
}
}
}
}

Can anyone please help me?

Thanks.
Best regards,
Hugo


(Hugo) #3

Hi Shay,

Thanks for the help! I've changed to the nested mapping and now its working.

Best regards,
Hugo

On Tuesday, March 6, 2012 9:01:17 PM UTC, kimchy wrote:

You need to use nested mapping to treat inner array of objects as a "self
sufficient" document, and then use nested filter / query. See more here:
http://www.elasticsearch.org/guide/reference/mapping/nested-type.html.

Also, note you use things like prefix filter, and that part is not
analyzed. So, if you index desc as "First Store", the terms created are
"first" and "store" (by the default standard analyzer), which means using
prefix filter (or query) with "First" will not match anything.

On Tuesday, March 6, 2012 at 7:59 PM, Hugo wrote:

Hi all,

I have a document structure like this:

{
"_index": "building",
"_type": "info",
"_source": {
"name": "First building",
"security_level": 1,
"state": 1,
"description": "first area obs",
"floors": [
{
"description": "First Store",
"name": "First floor",
"security_level": 2
},
{
"description": "Second Store",
"name": "Second floor",
"security_level": 1
}
]
}
}

and I want to search by floor name/description and/or building
name/description but omitting the results if the user does not have the
correct security level.
For instance if I try to find "First" and my security_level is 0 I should
not get any hit, but if my security level is 1 or 2 I should get one hit.
Also if I try to find "Store" and my security_level is 0 I should not get
any hit, but if my security level is 1 or 2 I should get one hit.

I've tried using the following query (for a user with security_level equal
to 1) but is does not work because it filters all documents that have one
or more floors.security_level equal to 2, even if there are other
floors.security_level with 0 or 1 that match the other criteria.

{
"query" : {
"filtered" : {
"query" : { "match_all" : {} },
"filter" : {
"and" : [
{ "or" : [
{ "prefix" : { "name" : "Store" } },
{ "prefix" : { "description" : "Store" } },
{ "prefix" : { "floors.name" : "Store" } },
{ "prefix" : { "floors.description" : "Store" } }
]},
{ "not": { "filter" : { "term" : { "security_level" : 2 } } } },
{ "not": { "filter" : { "term" : { "floors.security_level" : 2 } } } }
]
}
}
}
}

Can anyone please help me?

Thanks.
Best regards,
Hugo


(system) #4