2017-11-02 1 views
0

Ich bin neu in Elasticsearch und müssen mit der Lösung des helfen folgende:Elasticsearch - Filter, Gruppe und zählen Ergebnisse für jede Gruppe

ich eine Reihe von Dokumenten, die mehrere Produkte enthalten. Ich möchte die Produkteigenschaft product_brand von "Apple" filtern und die Anzahl der Produkte ermitteln, die dem Filter entsprechen. Das Ergebnis sollte jedoch nach der Dokument-ID gruppiert werden, die auch Teil des Dokuments selbst ist (test_id).

Beispiel Dokument:

"test" : { 
    "test_id" : 19988, 
    "test_name" : "Test", 
}, 
"products" : [ 
    { 
     "product_id" : 1, 
     "product_brand" : "Apple" 
    }, 
    { 
     "product_id" : 2, 
     "product_brand" : "Apple" 
    }, 
    { 
     "product_id" : 3, 
     "product_brand" : "Samsung" 
    } 
] 

Das Ergebnis sollte:

{ 
    "key" : 19988, 
    "count" : 2 
}, 

In SQL wäre es etwa so aussehen:

SELECT test_id, COUNT(product_id) 
FROM `test` 
WHERE product_brand = 'Apple' 
GROUP BY test_id; 

Wie kann ich das erreichen?

Antwort

0

Ich denke, das Sie ziemlich nahe kommen sollte:

gelten diese
GET /test/_search 
{ 
    "_source": { 
    "includes": [ 
     "test.test_id", 
     "_score" 
    ] 
    }, 
    "query": { 
    "function_score": { 
     "query": { 
     "match": { 
      "products.product_brand.keyword": "Apple" 
     } 
     }, 
     "functions": [ 
     { 
      "script_score": { 
      "script": { 
       "source": "def matches=0; def products = params['_source']['products']; for(p in products){if(p.product_brand == params['brand']){matches++;}} return matches;", 
       "params": { 
       "brand": "Apple" 
       } 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

Dieser Ansatz eine function_score verwendet, aber man könnte auch zu einem Skript Feld bewegen, wenn Sie anders punkten wollte. Das oben Genannte passt nur zu Dokumenten, die ein untergeordnetes Produktobjekt haben, wobei der Markentext genau auf "Apple" eingestellt ist.

Sie müssen nur die Eingabe für die beiden Instanzen von Apple steuern. Alternativ könnten Sie in der Abfrage function_score alle Elemente abgleichen und nur auf den Punktestand achten. Die Ausgabe könnte wie folgt aussehen:

{ 
    "took": 1, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "skipped": 0, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 1, 
    "max_score": 2, 
    "hits": [ 
     { 
     "_index": "test", 
     "_type": "doc", 
     "_id": "AV99vrBpgkgblFY6zscA", 
     "_score": 2, 
     "_source": { 
      "test": { 
      "test_id": 19988 
      } 
     } 
     } 
    ] 
    } 
} 

Und die Zuordnungen im Index verwendete ich sah wie folgt aus:

{ 
    "test": { 
    "mappings": { 
     "doc": { 
     "properties": { 
      "products": { 
      "properties": { 
       "product_brand": { 
       "type": "text", 
       "fields": { 
        "keyword": { 
        "type": "keyword", 
        "ignore_above": 256 
        } 
       } 
       }, 
       "product_id": { 
       "type": "long" 
       } 
      } 
      }, 
      "test": { 
      "properties": { 
       "test_id": { 
       "type": "long" 
       }, 
       "test_name": { 
       "type": "text", 
       "fields": { 
        "keyword": { 
        "type": "keyword", 
        "ignore_above": 256 
        } 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
}