如何使用 Android App 知道特定文档存在于 Cloudant 数据库中

How to know that specific document is present in Cloudant Database using Android App

我已经通过我的 Android 应用程序在 Cloudant 数据库中成功创建了文档。但是我找不到 Cloudant 数据库中存在的特定文档。我试过的如下....

TabTwo_Fragment.java

package com.example.android02.insightapp11;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.cloudant.sync.datastore.BasicDocumentRevision;
import com.cloudant.sync.datastore.Datastore;
import com.cloudant.sync.datastore.DatastoreManager;
import com.cloudant.sync.datastore.DatastoreNotCreatedException;
import com.cloudant.sync.datastore.DocumentBodyFactory;
import com.cloudant.sync.datastore.DocumentException;
import com.cloudant.sync.datastore.DocumentNotFoundException;
import com.cloudant.sync.datastore.DocumentRevision;
import com.cloudant.sync.datastore.MutableDocumentRevision;
import com.cloudant.sync.replication.Replicator;
import com.cloudant.sync.replication.ReplicatorBuilder;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

/**
 * A simple {@link Fragment} subclass.
 */
public class TabTwo_Fragment extends Fragment implements View.OnClickListener, SharedPreferences.OnSharedPreferenceChangeListener {

    private static final String DATASTORE_MANGER_DIR = "data";
    private static final String TASKS_DATASTORE_NAME = "tasks";

    Datastore DataStore;
    private Replicator PushReplicator, PullReplicator;
    DocumentRevision revision;

    static final String CLOUDANT_USER = "user_default";
    static final String CLOUDANT_DB = "database_name";
    static final String CLOUDANT_API_KEY = "api_key";
    static final String CLOUDANT_API_SECRET = "api_key_pwd";

    long TWITTER_ID = MainActivity.twitterID;
    String TWITTER_NAME = MainActivity.userName;

    Button btn_submit;
    Spinner sp1, sp2, sp3, sp4, sp5, sp6, sp7, sp8;
    TextView ans_total;

    String user = "old";
    HashMap<String, String> qa_hashmap;

    public TabTwo_Fragment() {
        // Required empty public constructor
    }

    public static TabTwo_Fragment newInstance() {
        return new TabTwo_Fragment();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.tabtwo_fragment, container, false);
        try {
            init(rootView);
        } catch (DocumentNotFoundException e) {
        } catch (DocumentException e) {
        } catch (URISyntaxException e) {
        }
        return rootView;
    }

    void init(View rootView) throws DocumentException, URISyntaxException {
        Log.e("init: ", "in init");
        find_view_by_id(rootView);
        registerClickEvents();
        defaultConfig();
        checkForRegisteredUser();
    }

    void find_view_by_id(View rootView) {
        Log.e("find_view_by_id: ", "in find_view_by_id");
        btn_submit = (Button) rootView.findViewById(R.id.btn_submit);
        sp1 = (Spinner) rootView.findViewById(R.id.sp1);
        sp2 = (Spinner) rootView.findViewById(R.id.sp2);
        sp3 = (Spinner) rootView.findViewById(R.id.sp3);
        sp4 = (Spinner) rootView.findViewById(R.id.sp4);
        sp5 = (Spinner) rootView.findViewById(R.id.sp5);
        sp6 = (Spinner) rootView.findViewById(R.id.sp6);
        sp7 = (Spinner) rootView.findViewById(R.id.sp7);
        sp8 = (Spinner) rootView.findViewById(R.id.sp8);
        ans_total = (TextView) rootView.findViewById(R.id.ans_total);
    }

    void registerClickEvents() {
        Log.e("registerClickEvents: ", "in registerClickEvents");
        btn_submit.setOnClickListener(this);
    }

    void defaultConfig() {
        Log.e("defaultConfig: ", "in defaultConfig");
        PreferenceManager.setDefaultValues(getContext(), R.xml.preferences, false);
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
        sharedPref.registerOnSharedPreferenceChangeListener(this);

        File path = getContext().getDir(DATASTORE_MANGER_DIR, Context.MODE_PRIVATE);
        DatastoreManager manager = new DatastoreManager(path.getAbsolutePath());

        try {
            DataStore = manager.openDatastore(TASKS_DATASTORE_NAME);
            setUriPlusReplicators();
        } catch (DatastoreNotCreatedException e) {
            Toast.makeText(getContext(), "Unable to open Datastore!", Toast.LENGTH_SHORT).show();
        } catch (URISyntaxException e) {
            Toast.makeText(getContext(), "URI Exception!!", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        try {
            setUriPlusReplicators();
        } catch (URISyntaxException e) {
        }
    }

    void setUriPlusReplicators() throws URISyntaxException {
        Log.e("setUriPlusReplicators: ", "in setUriPlusReplicators");
        URI uri = this.createServerUri();
        Log.e("URI: ", "" + uri);
        PushReplicator = ReplicatorBuilder.push().from(DataStore).to(uri).build();
        PushReplicator.getEventBus().register(this);
        PullReplicator = ReplicatorBuilder.pull().to(DataStore).from(uri).build();
        PullReplicator.getEventBus().register(this);
    }

    private URI createServerUri() throws URISyntaxException {
        Log.e("createServerUri: ", "in createServerUri");
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
        String username = sharedPref.getString(CLOUDANT_USER, "");
        String dbName = sharedPref.getString(CLOUDANT_DB, "");
        String apiKey = sharedPref.getString(CLOUDANT_API_KEY, "");
        String apiSecret = sharedPref.getString(CLOUDANT_API_SECRET, "");
        String host = username + ".cloudant.com";
        return new URI("https", apiKey + ":" + apiSecret, host, 443, "/" + dbName, null, null);
    }

    private URI createServerUri2(long twitterId) throws URISyntaxException {
        Log.e("createServerUri2: ", "in createServerUri2");
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getContext());
        String username = sharedPref.getString(CLOUDANT_USER, "");
        String dbName = sharedPref.getString(CLOUDANT_DB, "");
        String apiKey = sharedPref.getString(CLOUDANT_API_KEY, "");
        String apiSecret = sharedPref.getString(CLOUDANT_API_SECRET, "");
        String host = username + ".cloudant.com";
        return new URI("https", apiKey + ":" + apiSecret, host, 443, "/" + dbName + "/_all_docs?", null, null);
    }

    void checkForRegisteredUser() throws DocumentNotFoundException, DocumentException, URISyntaxException {
        BasicDocumentRevision retrieved = DataStore.getDocument(TWITTER_ID + "");
        if (user.equals("new")) {
            setQuizData(retrieved.getBody().toString());
        } else {
            newUser();
        }
    }

    void setQuizData(String DataRetrieved) {
        Log.e("setQuizData: ", "In setQuizData");
        user = "old";
        Log.e("DataRetrieved: ", "In " + DataRetrieved);
        String[] ANSWERS = getResources().getStringArray(R.array.ans);
        try {
            JSONObject jsonObject = new JSONObject(DataRetrieved);
            JSONObject jsonObject1 = jsonObject.getJSONObject("questions");
            String qs1 = jsonObject1.getString("q1");
            String qs2 = jsonObject1.getString("q2");
            String qs3 = jsonObject1.getString("q3");
            String qs4 = jsonObject1.getString("q4");
            String qs5 = jsonObject1.getString("q5");
            String qs6 = jsonObject1.getString("q6");
            String qs7 = jsonObject1.getString("q7");
            String qs8 = jsonObject1.getString("q8");

            sp1.setSelection(Arrays.asList(ANSWERS).indexOf(qs1));
            sp2.setSelection(Arrays.asList(ANSWERS).indexOf(qs2));
            sp3.setSelection(Arrays.asList(ANSWERS).indexOf(qs3));
            sp4.setSelection(Arrays.asList(ANSWERS).indexOf(qs4));
            sp5.setSelection(Arrays.asList(ANSWERS).indexOf(qs5));
            sp6.setSelection(Arrays.asList(ANSWERS).indexOf(qs6));
            sp7.setSelection(Arrays.asList(ANSWERS).indexOf(qs7));
            sp8.setSelection(Arrays.asList(ANSWERS).indexOf(qs8));
        } catch (JSONException e) {
        }
    }

    void newUser() {
        Log.e("newUser: ", "In newUser");
        user = "new";
    }

    void createDocument() throws DocumentException {
        Log.e("createDocument: ", "In createDocument");
        MutableDocumentRevision rev = new MutableDocumentRevision();
        rev.docId = TWITTER_ID + "";
        gatherQAData();

        /*HashMap<String, Object> map_main = new HashMap<String, Object>();*/
        HashMap<String, Object> map = new HashMap<String, Object>();
        ArrayList<HashMap<String, Object>> arrayTeachers = new ArrayList<>();

        map.put("twitter_id", TWITTER_ID + "");
        map.put("twitter_name", TWITTER_NAME);
        map.put("questions", qa_hashmap);
        /*arrayTeachers.add(map);*/
        /*map_main.put("user", arrayTeachers);*/

        rev.body = DocumentBodyFactory.create(map);
        revision = DataStore.createDocumentFromRevision(rev);
        PushReplicator.start();
    }

    void updateDocument() {
        Log.e("updateDocument: ", "In updateDocument");
    }

    void gatherQAData() {
        Log.e("gatherQAData: ", "In gatherQAData");
        qa_hashmap = new HashMap<String, String>();
        String a1, a2, a3, a4, a5, a6, a7, a8;
        a1 = sp1.getSelectedItem().toString();
        a2 = sp2.getSelectedItem().toString();
        a3 = sp3.getSelectedItem().toString();
        a4 = sp4.getSelectedItem().toString();
        a5 = sp5.getSelectedItem().toString();
        a6 = sp6.getSelectedItem().toString();
        a7 = sp7.getSelectedItem().toString();
        a8 = sp8.getSelectedItem().toString();
        qa_hashmap.put("q1", a1);
        qa_hashmap.put("q2", a2);
        qa_hashmap.put("q3", a3);
        qa_hashmap.put("q4", a4);
        qa_hashmap.put("q5", a5);
        qa_hashmap.put("q6", a6);
        qa_hashmap.put("q7", a7);
        qa_hashmap.put("q8", a8);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_submit:
                if (user.equals("new")) {
                    try {
                        createDocument();
                    } catch (DocumentException e) {
                    }
                } else {
                    updateDocument();
                }
                break;
            default:
        }
    }
}

我可以获取存储在 DataStore 中的文档。但是我无法将文档存储在 Cloudant 数据库中。

仅供参考:我正在 checkForRegisteredUser 方法中查找文档。

是的,我做到了。下面是我的 checkForRegisteredUser 方法 TabTwo_Fragment.java

的代码
void checkForRegisteredUser() {
        String url = "https://your_cloudant_user_name.cloudant.com/" + DB_NAME + "/" + DOC_ID;
        RequestQueue requestQueue = Volley.newRequestQueue(getContext());
        JsonObjectRequest jor = new JsonObjectRequest(Request.Method.GET, url, (String) null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                if (response.toString().length() > 0) {
                    setQuizData(response.toString());
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                newUser();
            }
        });
        requestQueue.add(jor);

这是官方文档LINK

这里DOC_ID是你要查看的文档id。希望这会对某人有所帮助。

Cloudant 中发生的事情是,默认情况下,cloudant 已经为每个文档提供了两个字段,即 _id 和 _rev,其中 _id 充当索引的主键。所以在 _id 字段上会有一个由 cloudant 创建的默认索引。如果您的文档中已有这些字段,那么 cloudant 将不会插入额外的 _id 和 _rev。 现在你可以在你的文档中有这个 _id 字段并根据你自己设置它或者让 cloudant 设置它。但是当您不设置它时,您将无法在主索引上查询 Cloudant,因为您不知道文档的 _id。 因此,要在存储的 twitter_id 等其他字段的基础上进行搜索或查找,您必须创建一个比 search/find 所能创建的索引更多的索引。 我们可以使用 cloudant api

提供的函数在 java 中创建索引
public void createIndex(java.lang.String indexName,
               java.lang.String designDocName,
               java.lang.String indexType,
               IndexField[] fields)

或者如果你在你的函数中分配 _id 而不是你可以简单地调用一个函数

db.contains(doc_id);

这要容易得多,因为您不需要创建任何索引并使用默认索引。

编辑-1 所以这里的db就是你获取的数据库实例。

Database db=client.database(db_name,create_flag);

其中 create_flag 是一个 布尔值 表示如果数据库不存在则应创建所以 true 表示是 create false意思是不存在就不要创建。 客户端是 CloudantClient 对象。 但是,如果您知道数据库不存在,您也可以调用 createDB。您可以按照以下方式进行

Database db=client.createDB("DBNAME");

如何获取 CloudantClient 取决于您使用的 cloudant api 版本。对于 ex 1.0.1 与最新版本不同。 在版本 1.0.1 中,您可以按照以下方式进行操作

CloudantClient client=new CloudantClient(URL_OF_YOUR_CLOUDANT,USERNAME,PASSWORD);

但在最新版本中他们使用

CloudantClient client=ClientBuilder.url(new URL("your url")).username("your username string").password("your password").build();

所以我不知道您为什么找不到 createIndex。我想您无法找到 Cloudant-api javadocs 。只需 google for Cloudant javadocs 或检查此 github GitHub link