You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Couchbase Lite Android 1.4.0:按值排序Map/Reduce并获取特定患者数据

Got it, let's break this down step by step since you're sticking with Couchbase Lite Android 1.4.0 and can't upgrade to 2.x yet. I'll cover the Map/Reduce view design, filtering logic, query implementation, and solve the value-sorting challenge.

1. Map/Reduce View Design

First, we need a view that identifies valid, open visits, then maps them to their associated patients. We'll use a Map function to filter qualifying visits, and a Reduce function to aggregate patients with at least one matching visit.

Map Function

This function processes only VISIT documents, checks the validity and open status, then emits the associated patient ID as the key (I'm assuming your VISIT docs have a patientId field linking to the patient's _id; adjust if your association works the other way).

function(doc) {
  // Target only VISIT documents
  if (doc.type === 'VISIT') {
    // Check if the visit is active (inactive is not true, or missing)
    const isActive = !doc.inactive;
    // Check if the visit is open (endDateTime is null or missing)
    const isOpen = doc.endDateTime == null;

    if (isActive && isOpen) {
      // Emit patient ID as key, 1 as value for aggregation
      emit(doc.patientId, 1);
    }
  }
}

Reduce Function

Use the built-in _count reducer to tally how many valid open visits each patient has. We only care about patients with a count ≥ 1.

_count
2. Android Query Implementation

First, register the view in your Android code, then query it to get valid patient IDs, then fetch the corresponding patient docs with only the fields you need.

Step 1: Register the View

// Get your database instance
Database db = getDatabase(); // Replace with your actual database access logic

// Create or retrieve the view
View activeOpenVisitsView = db.getView("active_open_visits_by_patient");
activeOpenVisitsView.setMapReduce(new MapReduce() {
    @Override
    public void map(Map<String, Object> doc, Emitter emitter) {
        // Translate the JS map logic to Java
        if ("VISIT".equals(doc.get("type"))) {
            Boolean inactive = (Boolean) doc.get("inactive");
            boolean isActive = inactive == null || !inactive;
            
            Object endDateTime = doc.get("endDateTime");
            boolean isOpen = endDateTime == null;
            
            if (isActive && isOpen) {
                String patientId = (String) doc.get("patientId");
                if (patientId != null) {
                    emitter.emit(patientId, 1);
                }
            }
        }
    }

    @Override
    public Object reduce(List<Object> values, boolean rereduce) {
        // Implement count aggregation
        return values.size();
    }
}, "1.0"); // Increment version if you update the view logic

Step 2: Get Valid Patient IDs

// Query the view with grouping to get patient-specific counts
Query visitQuery = activeOpenVisitsView.createQuery();
visitQuery.setReduce(true);
visitQuery.setGroupLevel(1); // Group results by patient ID

Set<String> validPatientIds = new HashSet<>();
QueryEnumerator visitEnumerator = visitQuery.run();

try {
    while (visitEnumerator.hasNext()) {
        QueryRow row = visitEnumerator.next();
        Integer visitCount = (Integer) row.getValue();
        // Keep patients with at least one valid open visit
        if (visitCount >= 1) {
            validPatientIds.add((String) row.getKey());
        }
    }
} finally {
    visitEnumerator.close();
}

Step 3: Fetch Patients with Required Fields & Sort

Now query the PATIENT documents, filter to only valid IDs, project just id and name, and sort as needed.

// Build patient query
Query patientQuery = db.createQuery();
patientQuery.setDocType("PATIENT");
// Filter to only patients with valid visits
patientQuery.where(Expression.property("_id").in(validPatientIds));
// Project only the fields you need: _id (as "id") and name
patientQuery.select(Expression.property("_id"), Expression.property("name"));
// Sort by name (adjust to your desired sort field)
patientQuery.orderBy(Sort.property("name").ascending());

// Execute and collect results
List<Map<String, Object>> patientResults = new ArrayList<>();
QueryEnumerator patientEnumerator = patientQuery.run();

try {
    while (patientEnumerator.hasNext()) {
        QueryRow row = patientEnumerator.next();
        Map<String, Object> patient = new HashMap<>();
        patient.put("id", row.getKey());
        patient.put("name", row.get("name"));
        patientResults.add(patient);
    }
} finally {
    patientEnumerator.close();
}

// patientResults now contains your filtered, sorted patient list
3. Solving Map/Reduce Value Sorting

Couchbase Lite 1.4's Map/Reduce views sort results by key by default. To sort by the Reduce value (e.g., number of valid visits), you'll need to sort the results client-side after fetching them:

// Fetch all Reduce results first
List<QueryRow> reduceRows = new ArrayList<>();
while (visitEnumerator.hasNext()) {
    reduceRows.add(visitEnumerator.next());
}

// Sort by visit count (descending order)
Collections.sort(reduceRows, new Comparator<QueryRow>() {
    @Override
    public int compare(QueryRow o1, QueryRow o2) {
        Integer count1 = (Integer) o1.getValue();
        Integer count2 = (Integer) o2.getValue();
        return count2.compareTo(count1); // Reverse for descending; use compareTo for ascending
    }
});

// Now extract patient IDs from the sorted rows and fetch patients as before
Set<String> sortedPatientIds = new LinkedHashSet<>(); // Preserve sort order
for (QueryRow row : reduceRows) {
    sortedPatientIds.add((String) row.getKey());
}

// Use sortedPatientIds in your patient query to maintain the order

Notes to Adjust for Your Schema

  • If your PATIENT docs use visitId to link to VISIT docs (instead of VISIT having patientId), swap the logic: filter valid VISIT docs, emit their _id as key, then fetch PATIENT docs where visitId is in the valid visit IDs.
  • If inactive is a string (e.g., "true"/"false") instead of a boolean, update the validity check to !"true".equals(doc.get("inactive")).

内容的提问来源于stack exchange,提问作者MHogge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:27:04