我正在使用MongoDB,我有以下结构:
websites
和
seo_keywords
因此,文档如下所示:
{
"_id" : ObjectId("58503934034b512b419a6eab"),
"website" : "https://www.google.com",
"keywords" : [
"testing",
"search",
"engine"
]
}
在帖子中包含一个集合:
{
"_id" : ObjectId("5873656cf632580b98e889b4"),
"position" : 2,
"keyword" : "search",
"found_url" : "https://google.com/"
}
我希望能够将这两者链接在一起,这样我就可以查询seo_keywords
所有google
网站的{
"_id" : ObjectId("5873656cf632580b98e889b4"),
"position" : 2,
"keyword" : "search",
"found_url" : "https://google.com/",
"website" : [
"_id" : ObjectId("58503934034b512b419a6eab"),
"website" : "https://www.google.com",
"keywords" : [
"testing",
"search",
"engine"
]
]
}
最好/最有效的方法是什么?我已经读过以下方法可以达到这个目的:
package com.cooltechworks.creditcarddesign;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.text.InputFilter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.cooltechworks.creditcarddesign.pager.AddCardTkn;
import com.cooltechworks.creditcarddesign.pager.CardCVVFragment;
import com.cooltechworks.creditcarddesign.pager.CardFragmentAdapter;
import com.cooltechworks.creditcarddesign.pager.CardFragmentAdapter.ICardEntryCompleteListener;
import com.stripe.android.Stripe;
import com.stripe.android.TokenCallback;
import com.stripe.android.model.Card;
import com.stripe.android.model.Token;
import static com.cooltechworks.creditcarddesign.CreditCardUtils.EXTRA_CARD_CVV;
import static com.cooltechworks.creditcarddesign.CreditCardUtils.EXTRA_CARD_EXPIRY;
import static com.cooltechworks.creditcarddesign.CreditCardUtils.EXTRA_CARD_HOLDER_NAME;
import static com.cooltechworks.creditcarddesign.CreditCardUtils.*;
public class CardEditFragment extends Fragment {
//public static final String STRIPE_PUBLISHABLE_KEY = "pk_live_xxxxxxxxxxx";
public static String STRIPE_PUBLISHABLE_KEY = "pk_test_xxxxxxxxxxx";
private TextView tvNext;
private TextView tvPrevious;
int mLastPageSelected = 0;
private CreditCardView mCreditCardView;
private ViewPager pager;
private String mCardNumber;
private String mCVV;
private String mCardHolderName;
private String mExpiry;
private String mPostcode;
private CardFragmentAdapter mCardAdapter;
private AddCardTkn tknHandlerDelegate;
private View editCardView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final View editCardView = inflater.inflate(R.layout.activity_card_edit, container, false);
this.editCardView = editCardView;
tknHandlerDelegate = getActivity().getIntent().getParcelableExtra("interface");
tvNext = (TextView) editCardView.findViewById(R.id.next);
tvPrevious = (TextView) editCardView.findViewById(R.id.previous);
tvNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pager = (ViewPager) editCardView.findViewById(R.id.card_field_container_pager);
int max = pager.getAdapter().getCount();
if (pager.getCurrentItem() == max - 1) {
// if last card.
onDoneTapped();
} else {
showNext();
}
}
});
tvPrevious.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPrevious();
}
});
setKeyboardVisibility(true);
mCreditCardView = (CreditCardView) editCardView.findViewById(R.id.credit_card_view);
if (savedInstanceState != null) {
checkParams(savedInstanceState);
} else {
checkParams(getActivity().getIntent().getExtras());
}
loadPager();
return editCardView;
}
private void checkParams(Bundle bundle) {
if (bundle == null) {
return;
}
mCardHolderName = bundle.getString(EXTRA_CARD_HOLDER_NAME);
mCVV = bundle.getString(EXTRA_CARD_CVV);
mExpiry = bundle.getString(EXTRA_CARD_EXPIRY);
mCardNumber = bundle.getString(EXTRA_CARD_NUMBER);
mCreditCardView.setCVV(mCVV);
mCreditCardView.setCardHolderName(mCardHolderName);
mCreditCardView.setCardExpiry(mExpiry);
mCreditCardView.setCardNumber(mCardNumber);
if (mCardAdapter != null) {
mCardAdapter.notifyDataSetChanged();
}
}
public void refreshNextButton() {
ViewPager pager = (ViewPager) editCardView.findViewById(R.id.card_field_container_pager);
int max = pager.getAdapter().getCount();
int text = R.string.next;
if (pager.getCurrentItem() == max - 1) {
text = R.string.done;
}
((TextView) editCardView.findViewById(R.id.next)).setText(text);
}
public void loadPager() {
ViewPager pager;
pager = (ViewPager) editCardView.findViewById(R.id.card_field_container_pager);
if (pager != null) {
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
CardCVVFragment cvvFrag = (CardCVVFragment) mCardAdapter.getItem(2);
int maxLength = 3;
if (mCardNumber.length() == 15) {
cvvFrag.isAmex = true;
maxLength = 4;
} else {
cvvFrag.isAmex = false;
}
InputFilter[] fArray = new InputFilter[1];
fArray[0] = new InputFilter.LengthFilter(maxLength);
cvvFrag.getCardCVVView().setFilters(fArray);
mCardAdapter.focus(position);
if (position == 2 && !cvvFrag.isAmex) {
mCreditCardView.showBack();
} else if ((position == 1 && mLastPageSelected == 2) || (position == 3 && !cvvFrag.isAmex)) {
mCreditCardView.showFront();
}
mLastPageSelected = position;
refreshNextButton();
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
pager.setOffscreenPageLimit(5);
}
mCardAdapter = new CardFragmentAdapter(getActivity().getSupportFragmentManager(), getActivity().getIntent().getExtras());
mCardAdapter.setOnCardEntryCompleteListener(new ICardEntryCompleteListener() {
@Override
public void onCardEntryComplete(int currentIndex) {
showNext();
}
@Override
public void onCardEntryEdit(int currentIndex, String entryValue) {
switch (currentIndex) {
case 0:
mCardNumber = entryValue.replace(CreditCardUtils.SPACE_SEPERATOR, "");
mCreditCardView.setCardNumber(mCardNumber);
break;
case 1:
mExpiry = entryValue;
mCreditCardView.setCardExpiry(entryValue);
break;
case 2:
mCVV = entryValue;
mCreditCardView.setCVV(entryValue);
break;
case 3:
mCardHolderName = entryValue;
mCreditCardView.setCardHolderName(entryValue);
break;
case 4:
mPostcode = entryValue;
mCreditCardView.setCardPostcode(entryValue);
break;
}
}
});
pager.setAdapter(mCardAdapter);
}
public void onSaveInstanceState(Bundle outState) {
outState.putString(EXTRA_CARD_CVV, mCVV);
outState.putString(EXTRA_CARD_HOLDER_NAME, mCardHolderName);
outState.putString(EXTRA_CARD_EXPIRY, mExpiry);
outState.putString(EXTRA_CARD_NUMBER, mCardNumber);
outState.putString(EXTRA_REGISTERED_POSTCODE, mPostcode);
super.onSaveInstanceState(outState);
}
public void showPrevious() {
final ViewPager pager = (ViewPager) editCardView.findViewById(R.id.card_field_container_pager);
int currentIndex = pager.getCurrentItem();
if (currentIndex - 1 >= 0) {
pager.setCurrentItem(currentIndex - 1);
}
refreshNextButton();
}
public void showNext() {
final ViewPager pager = (ViewPager) editCardView.findViewById(R.id.card_field_container_pager);
CardFragmentAdapter adapter = (CardFragmentAdapter) pager.getAdapter();
int max = adapter.getCount();
int currentIndex = pager.getCurrentItem();
if (currentIndex + 1 < max) {
pager.setCurrentItem(currentIndex + 1);
} else {
// completed the card entry.
setKeyboardVisibility(false);
}
refreshNextButton();
}
private void onDoneTapped() {
if (mCardHolderName == null || mCardHolderName.equals(""))
{
handleError("Please enter the cardholders name");
return;
}
if (mPostcode == null || mPostcode.equals(""))
{
handleError("Please enter the cardholders postcode");
return;
}
if (mExpiry == null || mExpiry.length() != 5) {
handleError("The expiration date that you entered is invalid");
return;
}
String month = mExpiry.substring(0, 2);
String year = mExpiry.substring(3);
Card card = new Card(mCardNumber,
Integer.parseInt(month),
Integer.parseInt(year),
mCVV,
mCardHolderName,
"",
"",
"",
"",
mPostcode,
"",
"");
boolean validation = card.validateCard();
if (validation) {
startProgress();
new Stripe().createToken(
card,
STRIPE_PUBLISHABLE_KEY,
new TokenCallback() {
public void onSuccess(Token token) {
//Send to server
Log.d("Stripe Token", token.toString());
//For purpose of booking while Not registered yet
Bundle appointmentInfo = getActivity().getIntent().getExtras();
tknHandlerDelegate.addCard(token.getId(), getActivity(), appointmentInfo);
}
public void onError(Exception error) {
handleError(error.getLocalizedMessage());
finishProgress();
}
});
} else if (!card.validateNumber()) {
handleError("The card number that you entered is invalid");
} else if (!card.validateExpiryDate()) {
handleError("The expiration date that you entered is invalid");
} else if (!card.validateCVC()) {
handleError("The CVC code that you entered is invalid");
} else {
handleError("The card details that you entered are invalid");
}
}
private void startProgress() {
tknHandlerDelegate.showProgress(getActivity());
}
private void finishProgress() {
tknHandlerDelegate.hideProgress(getActivity());
}
private void handleError(String error) {
tknHandlerDelegate.handleError(error, getActivity());
}
// from the link above
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
LinearLayout parent = (LinearLayout) editCardView.findViewById(R.id.parent);
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) parent.getLayoutParams();
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, 0);
parent.setLayoutParams(layoutParams);
}
}
private void setKeyboardVisibility(boolean visible) {
final EditText editText = (EditText) editCardView.findViewById(R.id.card_number_field);
if (!visible) {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
} else {
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
}
}
但这是最有效的方法吗?我可以不使用ID或实际网站将文档链接在一起吗?
答案 0 :(得分:1)
如果我们的关系密钥在两个集合中都相似,我们可以尝试使用$lookup,因为它提供了MongoDB 3.2+的加入。
db.posts.aggregate([
{
$lookup:
{
from: "websites",
localField: "found_url",
foreignField: "website",
as: "post_websites"
}
}
])