所以我有这个映射:
"employee": {
"properties": {
"DaysOff": {
"type": "nested",
"properties": {
"Date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"Days": {
"type": "double"
},
"ID": {
"type": "long"
}
}
}
}
}
所以基本上一个员工可以休息几天。他们每天休息都存放在属性DaysOff
下的数组中。 Days
可能只有一天的一小部分,所以如果员工休息半天,那么0.5
就可以了。
所以我有这个搜索:
{
"size": 45,
"filter": {
"nested": {
"path": "DaysOff",
"filter": {
"range": {
"DaysOff.Date": {
"from": "now-2M",
"to": "now"
}
}
}
}
}
}
它带回了45个文件。哪个是对的。我现在无法弄清楚如何将聚合应用于这些文档,以便找回已经采取的所有日期的总和。
使用此resource我尝试了aggs
,但没有得到正确的结果:
{
"size": 45,
"filter": {
"nested": {
"path": "DaysOff",
"filter": {
"range": {
"DaysOff.Date": {
"from": "now-2M",
"to": "now"
}
}
}
}
},
"aggs": {
"sum_docs": {
"nested": {
"path": "DaysOff"
},
"aggs": {
"stepped_down": {
"sum": {
"field": "DaysOff.Days"
}
}
}
}
}
}
答案 0 :(得分:2)
您需要nested documents
POST employee
{
"mappings": {
"emp_map": {
"properties": {
"DaysOff": {
"type": "nested",
"properties": {
"Date": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"Days": {
"type": "double"
},
"ID": {
"type": "long"
}
}
},
"name": {
"type": "string"
}
}
}
}
},
才能获得正确的结果,来自文档
由于嵌套文档被索引为单独的文档,因此只能在嵌套查询的范围内访问它们,
我创建了像这样的索引
PUT employee/emp_map/1
{
"name" : "messi",
"DaysOff" : [
{
"Date" : "2015-11-01",
"Days" : 1,
"ID" : 11
},
{
"Date" : "2014-11-01",
"Days" : 2,
"ID" : 11
},
{
"Date" : "2015-12-01",
"Days" : 0.5,
"ID" : 11
}
]
}
PUT employee/emp_map/2
{
"name" : "ronaldo",
"DaysOff" : [
{
"Date" : "2015-10-01",
"Days" : 3,
"ID" : 12
},
{
"Date" : "2014-11-01",
"Days" : 2,
"ID" : 12
},
{
"Date" : "2015-12-01",
"Days" : 0.5,
"ID" : 12
}
]
}
PUT employee/emp_map/3
{
"name" : "suarez",
"DaysOff" : [
{
"Date" : "2015-11-01",
"Days" : 4,
"ID" : 13
},
{
"Date" : "2015-11-09",
"Days" : 2,
"ID" : 13
},
{
"Date" : "2015-12-01",
"Days" : 1.5,
"ID" : 13
}
]
}
然后我索引了几个像这样的文件,
filter aggregation
这是我的查询,请注意nested aggregation
中的GET employee/_search
{
"query": {
"bool": {
"filter": {
"nested": {
"path": "DaysOff",
"query": {
"range": {
"DaysOff.Date": {
"from": "now-2M",
"to": "now"
}
}
}
}
}
}
},
"aggs": {
"emp_name": {
"terms": {
"field": "name",
"size": 10
},
"aggs": {
"nesting": {
"nested": {
"path": "DaysOff"
},
"aggs": {
"filter_date": {
"filter": {
"range": {
"DaysOff.Date": {
"from": "now-2M",
"to": "now"
}
}
},
"aggs": {
"sum_taken_off_days": {
"sum": {
"field": "DaysOff.Days"
}
}
}
}
}
}
}
}
},
"size": 0
}
,如果没有ES会给你所有日期的总和。
"aggregations": {
"emp_name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "messi",
"doc_count": 1,
"nesting": {
"doc_count": 3,
"filter_date": {
"doc_count": 2,
"sum_taken_off_days": {
"value": 1.5
}
}
}
},
{
"key": "ronaldo",
"doc_count": 1,
"nesting": {
"doc_count": 3,
"filter_date": {
"doc_count": 1,
"sum_taken_off_days": {
"value": 0.5
}
}
}
},
{
"key": "suarez",
"doc_count": 1,
"nesting": {
"doc_count": 3,
"filter_date": {
"doc_count": 3,
"sum_taken_off_days": {
"value": 7.5
}
}
}
}
]
}
}
这是我得到的结果,
emp_name terms aggregation
P.S:这是每位员工,您可以删除import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
import entities.Order;
import entities.User;
public class HomeFragment extends Fragment implements TransAdapter.ClickListener {
private RecyclerView rvTrans;
private TransAdapter adapter;
private MenuItem mSearchAction;
private SearchView searchView;
private ActionBar actionBar;
private boolean isSearchOpened = false;
private EditText etSearch;
public HomeFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
rvTrans = (RecyclerView) view.findViewById(R.id.rv_transactions);
rvTrans.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new TransAdapter(getActivity());
adapter.setClickListener(this);
rvTrans.setAdapter(adapter);
try {
adapter.setOrderList(HomeActivity.backEnd.booksForSale());
} catch (Exception e) {
Toast.makeText(getActivity().getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
case R.id.action_search:
handleMenuSearch();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
mSearchAction = menu.findItem(R.id.action_search);
searchView = (SearchView) MenuItemCompat.getActionView(mSearchAction);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
adapter.clearData();
try {
adapter.setOrderList(HomeActivity.backEnd.bookGlobalSearch(query));
} catch (Exception e) {
Toast.makeText(getActivity().getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
@Override
public void itemClicked(Order order) {
Intent intent = new Intent(getActivity(), DetailsActivity.class);
intent.putExtra("BOOK_PICTURE", order.getBookPicture());
intent.putExtra("BOOK_NAME", order.getBookName());
intent.putExtra("BOOK_AUTHOR", order.getAuthorName());
intent.putExtra("BOOK_GENRE", order.getGenre());
intent.putExtra("BOOK_PUBLISHING", order.getPublishingYear());
startActivity(intent);
}
private void handleMenuSearch() {
actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar(); //get the actionbar
if(isSearchOpened){ //test if the search is open
if(actionBar != null)
{
actionBar.setDisplayShowCustomEnabled(false); //disable a custom view inside the actionbar
actionBar.setDisplayShowTitleEnabled(true); //show the title in the action bar
}
// hides the keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(etSearch.getWindowToken(), 0);
isSearchOpened = false;
} else { // open the search entry
if(actionBar != null)
{
actionBar.setDisplayShowCustomEnabled(true); //enable it to display a
// custom view in the action bar.
// action.setCustomView(R.layout.search_bar);//add the custom view
actionBar.setDisplayShowTitleEnabled(false); //hide the title
}
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etSearch, InputMethodManager.SHOW_IMPLICIT);
isSearchOpened = true;
}
}
}
以获得所有员工的总和。